summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/http/http_network_layer_unittest.cc74
-rw-r--r--net/http/http_network_transaction.cc31
-rw-r--r--net/proxy/proxy_service.h3
-rw-r--r--tools/metrics/histograms/histograms.xml1
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">