diff options
-rw-r--r-- | net/http/http_network_layer_unittest.cc | 74 | ||||
-rw-r--r-- | net/http/http_network_transaction.cc | 31 | ||||
-rw-r--r-- | net/proxy/proxy_service.h | 3 | ||||
-rw-r--r-- | tools/metrics/histograms/histograms.xml | 1 |
4 files changed, 100 insertions, 9 deletions
diff --git a/net/http/http_network_layer_unittest.cc b/net/http/http_network_layer_unittest.cc index 5534455..7fdfbc0 100644 --- a/net/http/http_network_layer_unittest.cc +++ b/net/http/http_network_layer_unittest.cc @@ -99,7 +99,8 @@ class HttpNetworkLayerTest : public PlatformTest { const std::string& bad_proxy2) { const ProxyRetryInfoMap& retry_info = proxy_service_->proxy_retry_info(); ASSERT_EQ(proxy_count, retry_info.size()); - ASSERT_TRUE(retry_info.find(bad_proxy) != retry_info.end()); + if (proxy_count > 0) + ASSERT_TRUE(retry_info.find(bad_proxy) != retry_info.end()); if (proxy_count > 1) ASSERT_TRUE(retry_info.find(bad_proxy2) != retry_info.end()); } @@ -135,7 +136,7 @@ class HttpNetworkLayerTest : public PlatformTest { MockRead data_reads[], int data_reads_size, std::string method, - std::string content, + std::string content_of_retry, bool retry_expected, unsigned int expected_retry_info_size) { std::string trailer = @@ -160,8 +161,8 @@ class HttpNetworkLayerTest : public PlatformTest { size_t data_reads2_index = 0; data_reads2[data_reads2_index++] = MockRead("HTTP/1.0 200 OK\r\n" "Server: not-proxy\r\n\r\n"); - if (!content.empty()) - data_reads2[data_reads2_index++] = MockRead(content.c_str()); + if (!content_of_retry.empty()) + data_reads2[data_reads2_index++] = MockRead(content_of_retry.c_str()); data_reads2[data_reads2_index++] = MockRead(SYNCHRONOUS, OK); MockWrite data_writes2[] = { @@ -174,7 +175,7 @@ class HttpNetworkLayerTest : public PlatformTest { // Expect that we get "content" and not "Bypass message", and that there's // a "not-proxy" "Server:" header in the final response. if (retry_expected) { - ExecuteRequestExpectingContentAndHeader(method, content, + ExecuteRequestExpectingContentAndHeader(method, content_of_retry, "server", "not-proxy"); } else { ExecuteRequestExpectingContentAndHeader(method, "Bypass message", "", ""); @@ -621,7 +622,8 @@ TEST_F(HttpNetworkLayerTest, ServerFallbackWithProxyTimedBypass) { MockRead data_reads[] = { MockRead("HTTP/1.1 200 OK\r\n" "Connection: keep-alive\r\n" - "Chrome-Proxy: bypass=86400\r\n\r\n"), + "Chrome-Proxy: bypass=86400\r\n" + "Via: 1.1 Chrome Compression Proxy\r\n\r\n"), MockRead("Bypass message"), MockRead(SYNCHRONOUS, OK), }; @@ -632,6 +634,63 @@ TEST_F(HttpNetworkLayerTest, ServerFallbackWithProxyTimedBypass) { (*proxy_service_->proxy_retry_info().begin()).second.current_delay); } +TEST_F(HttpNetworkLayerTest, ServerFallbackWithWrongViaHeader) { + // Verify that a Via header that lacks the Chrome-Proxy induces proxy fallback + // to a second proxy, if configured. + std::string chrome_proxy = GetChromeProxy(); + ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult( + "PROXY " + chrome_proxy + "; PROXY good:8080")); + + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n" + "Connection: keep-alive\r\n" + "Via: 1.0 some-other-proxy\r\n\r\n"), + MockRead("Bypass message"), + MockRead(SYNCHRONOUS, OK), + }; + + TestProxyFallbackWithMockReads(chrome_proxy, std::string(), data_reads, + arraysize(data_reads), 1u); +} + +TEST_F(HttpNetworkLayerTest, ServerFallbackWithNoViaHeader) { + // Verify that the lack of a Via header induces proxy fallback to a second + // proxy, if configured. + std::string chrome_proxy = GetChromeProxy(); + ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult( + "PROXY " + chrome_proxy + "; PROXY good:8080")); + + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n" + "Connection: keep-alive\r\n\r\n"), + MockRead("Bypass message"), + MockRead(SYNCHRONOUS, OK), + }; + + TestProxyFallbackWithMockReads(chrome_proxy, std::string(), data_reads, + arraysize(data_reads), 1u); +} + +TEST_F(HttpNetworkLayerTest, NoServerFallbackWithChainedViaHeader) { + // Verify that Chrome will not be induced to bypass the Chrome proxy when + // the Chrome Proxy via header is present, even if that header is chained. + std::string chrome_proxy = GetChromeProxy(); + ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult( + "PROXY " + chrome_proxy + "; PROXY good:8080")); + + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n" + "Connection: keep-alive\r\n" + "Via: 1.1 Chrome Compression Proxy, 1.0 some-other-proxy\r\n\r\n"), + MockRead("Bypass message"), + MockRead(SYNCHRONOUS, OK), + }; + + TestProxyFallbackByMethodWithMockReads(chrome_proxy, std::string(), + data_reads, arraysize(data_reads), + "GET", std::string(), false, 0); +} + #if defined(DATA_REDUCTION_FALLBACK_HOST) TEST_F(HttpNetworkLayerTest, ServerFallbackWithProxyTimedBypassAll) { // Verify that a Chrome-Proxy: block=<seconds> header bypasses a @@ -646,7 +705,8 @@ TEST_F(HttpNetworkLayerTest, ServerFallbackWithProxyTimedBypassAll) { MockRead data_reads[] = { MockRead("HTTP/1.1 200 OK\r\n" "Connection: keep-alive\r\n" - "Chrome-Proxy: block=86400\r\n\r\n"), + "Chrome-Proxy: block=86400\r\n" + "Via: 1.1 Chrome Compression Proxy\r\n\r\n"), MockRead("Bypass message"), MockRead(SYNCHRONOUS, OK), }; diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index 10501a4..96817e2 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc @@ -62,6 +62,7 @@ #include "url/gurl.h" #if defined(SPDY_PROXY_AUTH_ORIGIN) +#include <algorithm> #include "net/proxy/proxy_server.h" #endif @@ -118,6 +119,30 @@ base::Value* NetLogSSLVersionFallbackCallback( return dict; } +#if defined(SPDY_PROXY_AUTH_ORIGIN) +// Returns true if |response_headers| contains the data reduction proxy Via +// header value. +bool IsChromeProxyResponse(const net::HttpResponseHeaders* response_headers) { + if (!response_headers) { + return false; + } + const char kDataReductionProxyViaValue[] = "1.1 Chrome Compression Proxy"; + size_t value_len = strlen(kDataReductionProxyViaValue); + void* iter = NULL; + std::string temp; + while (response_headers->EnumerateHeader(&iter, "Via", &temp)) { + std::string::const_iterator it = + std::search(temp.begin(), temp.end(), + kDataReductionProxyViaValue, + kDataReductionProxyViaValue + value_len, + base::CaseInsensitiveCompareASCII<char>()); + if (it != temp.end()) + return true; + } + return false; +} +#endif + } // namespace //----------------------------------------------------------------------------- @@ -1018,14 +1043,16 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) { #endif if (chrome_proxy_used || chrome_fallback_proxy_used) { - if (response_.headers->GetChromeProxyInfo(&chrome_proxy_info)) { + if (!IsChromeProxyResponse(response_.headers.get())) { + proxy_bypass_event = ProxyService::MISSING_VIA_HEADER; + } else if (response_.headers->GetChromeProxyInfo(&chrome_proxy_info)) { if (chrome_proxy_info.bypass_duration < TimeDelta::FromMinutes(30)) proxy_bypass_event = ProxyService::SHORT_BYPASS; else proxy_bypass_event = ProxyService::LONG_BYPASS; } else { // Additionally, fallback if a 500, 502 or 503 is returned via the data - // reduction proxy. This is conservative, as the 500, 501 or 502 might + // reduction proxy. This is conservative, as the 500, 502 or 503 might // have been generated by the origin, and not the proxy. if (response_.headers->response_code() == HTTP_INTERNAL_SERVER_ERROR || response_.headers->response_code() == HTTP_BAD_GATEWAY || diff --git a/net/proxy/proxy_service.h b/net/proxy/proxy_service.h index 1f77ad7..4755ed8 100644 --- a/net/proxy/proxy_service.h +++ b/net/proxy/proxy_service.h @@ -286,6 +286,9 @@ class NET_EXPORT ProxyService : public NetworkChangeNotifier::IPAddressObserver, // Bypass the proxy because of any other error. ERROR_BYPASS, + // Bypass the proxy because responses appear not to be coming via it. + MISSING_VIA_HEADER, + // This must always be last. BYPASS_EVENT_TYPE_MAX }; diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index b91ff28..2418ef4 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml @@ -23265,6 +23265,7 @@ other types of suffix sets. <int value="1" label="Long bypass"/> <int value="2" label="Bypass due to internal server error"/> <int value="3" label="Bypass due to other error"/> + <int value="4" label="Bypass due to missing via header"/> </enum> <enum name="DataReductionProxyProbeURLFetchResult" type="int"> |