| Index: net/http/http_network_layer_unittest.cc
|
| diff --git a/net/http/http_network_layer_unittest.cc b/net/http/http_network_layer_unittest.cc
|
| index a82dd007810c17e29bd55d4f55069aad5a74bca3..08917245ea86e20cf5ce157571e46dab7efc9b7d 100644
|
| --- a/net/http/http_network_layer_unittest.cc
|
| +++ b/net/http/http_network_layer_unittest.cc
|
| @@ -23,10 +23,15 @@ namespace {
|
|
|
| class HttpNetworkLayerTest : public PlatformTest {
|
| protected:
|
| - HttpNetworkLayerTest()
|
| - : cert_verifier_(new MockCertVerifier),
|
| - proxy_service_(ProxyService::CreateDirect()),
|
| - ssl_config_service_(new SSLConfigServiceDefaults) {
|
| + HttpNetworkLayerTest() : ssl_config_service_(new SSLConfigServiceDefaults) {}
|
| +
|
| + virtual void SetUp() {
|
| + ConfigureTestDependencies(ProxyService::CreateDirect());
|
| + }
|
| +
|
| + void ConfigureTestDependencies(ProxyService* proxy_service) {
|
| + cert_verifier_.reset(new MockCertVerifier);
|
| + proxy_service_.reset(proxy_service);
|
| HttpNetworkSession::Params session_params;
|
| session_params.client_socket_factory = &mock_socket_factory_;
|
| session_params.host_resolver = &host_resolver_;
|
| @@ -41,7 +46,7 @@ class HttpNetworkLayerTest : public PlatformTest {
|
| MockClientSocketFactory mock_socket_factory_;
|
| MockHostResolver host_resolver_;
|
| scoped_ptr<CertVerifier> cert_verifier_;
|
| - const scoped_ptr<ProxyService> proxy_service_;
|
| + scoped_ptr<ProxyService> proxy_service_;
|
| const scoped_refptr<SSLConfigService> ssl_config_service_;
|
| scoped_refptr<HttpNetworkSession> network_session_;
|
| scoped_ptr<HttpNetworkLayer> factory_;
|
| @@ -115,6 +120,176 @@ TEST_F(HttpNetworkLayerTest, GET) {
|
| EXPECT_EQ("hello world", contents);
|
| }
|
|
|
| +TEST_F(HttpNetworkLayerTest, ServerFallback) {
|
| + // Verify that a Connection: Proxy-Bypass header induces proxy fallback to
|
| + // a second proxy, if configured.
|
| +
|
| + // To configure this test, we need to wire up a custom proxy service to use
|
| + // a pair of proxies. We'll induce fallback via the first and return
|
| + // the expected data via the second.
|
| + ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
|
| + "PROXY bad:8080; PROXY good:8080"));
|
| +
|
| + MockRead data_reads[] = {
|
| + MockRead("HTTP/1.1 200 OK\r\n"
|
| + "Connection: proxy-bypass\r\n\r\n"),
|
| + MockRead("Bypass message"),
|
| + MockRead(SYNCHRONOUS, OK),
|
| + };
|
| + MockWrite data_writes[] = {
|
| + MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
|
| + "Host: www.google.com\r\n"
|
| + "Proxy-Connection: keep-alive\r\n\r\n"),
|
| + };
|
| + StaticSocketDataProvider data1(data_reads, arraysize(data_reads),
|
| + data_writes, arraysize(data_writes));
|
| + mock_socket_factory_.AddSocketDataProvider(&data1);
|
| +
|
| + // Second data provider returns the expected content.
|
| + MockRead data_reads2[] = {
|
| + MockRead("HTTP/1.0 200 OK\r\n"
|
| + "Server: not-proxy\r\n\r\n"),
|
| + MockRead("content"),
|
| + MockRead(SYNCHRONOUS, OK),
|
| + };
|
| + MockWrite data_writes2[] = {
|
| + MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
|
| + "Host: www.google.com\r\n"
|
| + "Proxy-Connection: keep-alive\r\n\r\n"),
|
| + };
|
| + StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
|
| + data_writes2, arraysize(data_writes2));
|
| + mock_socket_factory_.AddSocketDataProvider(&data2);
|
| +
|
| + TestCompletionCallback callback;
|
| +
|
| + HttpRequestInfo request_info;
|
| + request_info.url = GURL("http://www.google.com/");
|
| + request_info.method = "GET";
|
| + request_info.load_flags = LOAD_NORMAL;
|
| +
|
| + scoped_ptr<HttpTransaction> trans;
|
| + int rv = factory_->CreateTransaction(&trans, NULL);
|
| + EXPECT_EQ(OK, rv);
|
| +
|
| + rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
|
| + if (rv == ERR_IO_PENDING)
|
| + rv = callback.WaitForResult();
|
| + ASSERT_EQ(OK, rv);
|
| +
|
| + std::string contents;
|
| + rv = ReadTransaction(trans.get(), &contents);
|
| + EXPECT_EQ(OK, rv);
|
| +
|
| + // We should obtain content from the second socket provider write
|
| + // corresponding to the fallback proxy.
|
| + EXPECT_EQ("content", contents);
|
| + // We also have a server header here that isn't set by the proxy.
|
| + EXPECT_TRUE(trans->GetResponseInfo()->headers->HasHeaderValue(
|
| + "server", "not-proxy"));
|
| + // We should also observe the bad proxy in the retry list.
|
| + ASSERT_TRUE(1u == proxy_service_->proxy_retry_info().size());
|
| + EXPECT_EQ("bad:8080", (*proxy_service_->proxy_retry_info().begin()).first);
|
| +}
|
| +
|
| +TEST_F(HttpNetworkLayerTest, ServerFallbackDoesntLoop) {
|
| + // Verify that a Connection: Proxy-Bypass header will display the original
|
| + // proxy's error page content if a fallback option is not configured.
|
| + ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
|
| + "PROXY bad:8080; PROXY alsobad:8080"));
|
| +
|
| + MockRead data_reads[] = {
|
| + MockRead("HTTP/1.1 200 OK\r\n"
|
| + "Connection: proxy-bypass\r\n\r\n"),
|
| + MockRead("Bypass message"),
|
| + MockRead(SYNCHRONOUS, OK),
|
| + };
|
| + MockWrite data_writes[] = {
|
| + MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
|
| + "Host: www.google.com\r\n"
|
| + "Proxy-Connection: keep-alive\r\n\r\n"),
|
| + };
|
| + StaticSocketDataProvider data1(data_reads, arraysize(data_reads),
|
| + data_writes, arraysize(data_writes));
|
| + StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
|
| + data_writes, arraysize(data_writes));
|
| + mock_socket_factory_.AddSocketDataProvider(&data1);
|
| + mock_socket_factory_.AddSocketDataProvider(&data2);
|
| +
|
| + TestCompletionCallback callback;
|
| +
|
| + HttpRequestInfo request_info;
|
| + request_info.url = GURL("http://www.google.com/");
|
| + request_info.method = "GET";
|
| + request_info.load_flags = LOAD_NORMAL;
|
| +
|
| + scoped_ptr<HttpTransaction> trans;
|
| + int rv = factory_->CreateTransaction(&trans, NULL);
|
| + EXPECT_EQ(OK, rv);
|
| +
|
| + rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
|
| + if (rv == ERR_IO_PENDING)
|
| + rv = callback.WaitForResult();
|
| + ASSERT_EQ(OK, rv);
|
| +
|
| + std::string contents;
|
| + rv = ReadTransaction(trans.get(), &contents);
|
| + EXPECT_EQ(OK, rv);
|
| + EXPECT_EQ("Bypass message", contents);
|
| +
|
| + // Despite not falling back to anything, we should still observe the proxies
|
| + // in the bad proxies list.
|
| + const ProxyRetryInfoMap& retry_info = proxy_service_->proxy_retry_info();
|
| + ASSERT_EQ(2u, retry_info.size());
|
| + ASSERT_TRUE(retry_info.find("bad:8080") != retry_info.end());
|
| + ASSERT_TRUE(retry_info.find("alsobad:8080") != retry_info.end());
|
| +}
|
| +
|
| +TEST_F(HttpNetworkLayerTest, ProxyBypassIgnoredOnDirectConnection) {
|
| + // Verify that a Connection: proxy-bypass header is ignored when returned
|
| + // from a directly connected origin server.
|
| + ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult("DIRECT"));
|
| +
|
| + MockRead data_reads[] = {
|
| + MockRead("HTTP/1.1 200 OK\r\n"
|
| + "Connection: proxy-bypass\r\n\r\n"),
|
| + MockRead("Bypass message"),
|
| + MockRead(SYNCHRONOUS, OK),
|
| + };
|
| + MockWrite data_writes[] = {
|
| + MockWrite("GET / HTTP/1.1\r\n"
|
| + "Host: www.google.com\r\n"
|
| + "Connection: keep-alive\r\n\r\n"),
|
| + };
|
| + StaticSocketDataProvider data1(data_reads, arraysize(data_reads),
|
| + data_writes, arraysize(data_writes));
|
| + mock_socket_factory_.AddSocketDataProvider(&data1);
|
| + TestCompletionCallback callback;
|
| +
|
| + HttpRequestInfo request_info;
|
| + request_info.url = GURL("http://www.google.com/");
|
| + request_info.method = "GET";
|
| + request_info.load_flags = LOAD_NORMAL;
|
| +
|
| + scoped_ptr<HttpTransaction> trans;
|
| + int rv = factory_->CreateTransaction(&trans, NULL);
|
| + EXPECT_EQ(OK, rv);
|
| +
|
| + rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
|
| + if (rv == ERR_IO_PENDING)
|
| + rv = callback.WaitForResult();
|
| + ASSERT_EQ(OK, rv);
|
| +
|
| + // We should have read the original page data.
|
| + std::string contents;
|
| + rv = ReadTransaction(trans.get(), &contents);
|
| + EXPECT_EQ(OK, rv);
|
| + EXPECT_EQ("Bypass message", contents);
|
| +
|
| + // We should have no entries in our bad proxy list.
|
| + ASSERT_EQ(0u, proxy_service_->proxy_retry_info().size());
|
| +}
|
| +
|
| } // namespace
|
|
|
| } // namespace net
|
|
|