summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/http/http_network_transaction.cc3
-rw-r--r--net/http/http_network_transaction_unittest.cc108
-rw-r--r--net/http/http_stream_factory_impl.cc9
3 files changed, 115 insertions, 5 deletions
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 135d0e4..0733fdf 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -70,7 +70,8 @@ namespace {
void ProcessAlternativeServices(HttpNetworkSession* session,
const HttpResponseHeaders& headers,
const HostPortPair& http_host_port_pair) {
- if (headers.HasHeader(kAlternativeServiceHeader)) {
+ if (session->params().use_alternative_services &&
+ headers.HasHeader(kAlternativeServiceHeader)) {
std::string alternative_service_str;
headers.GetNormalizedHeader(kAlternativeServiceHeader,
&alternative_service_str);
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index f263777..03bf557 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -8781,6 +8781,66 @@ TEST_P(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
EXPECT_EQ(443, alternative_service_vector[0].port);
}
+// Alternative Service headers must be ignored when |use_alternative_services|
+// is false.
+TEST_P(HttpNetworkTransactionTest, DoNotHonorAlternativeServiceHeader) {
+ session_deps_.next_protos = SpdyNextProtos();
+ session_deps_.use_alternative_services = false;
+
+ std::string alternative_service_http_header =
+ GetAlternativeServiceHttpHeader();
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n"),
+ MockRead(alternative_service_http_header.c_str()),
+ MockRead("\r\n"),
+ MockRead("hello world"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("http://www.example.org/");
+ request.load_flags = 0;
+
+ StaticSocketDataProvider data(data_reads, arraysize(data_reads), nullptr, 0);
+
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ TestCompletionCallback callback;
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
+
+ int rv = trans->Start(&request, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ HostPortPair http_host_port_pair("www.example.org", 80);
+ HttpServerProperties& http_server_properties =
+ *session->http_server_properties();
+ AlternativeServiceVector alternative_service_vector =
+ http_server_properties.GetAlternativeServices(http_host_port_pair);
+ EXPECT_TRUE(alternative_service_vector.empty());
+
+ EXPECT_EQ(OK, callback.WaitForResult());
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+ ASSERT_TRUE(response != nullptr);
+ ASSERT_TRUE(response->headers.get() != nullptr);
+ EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
+ EXPECT_FALSE(response->was_fetched_via_spdy);
+ EXPECT_FALSE(response->was_npn_negotiated);
+
+ std::string response_data;
+ ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
+ EXPECT_EQ("hello world", response_data);
+
+ alternative_service_vector =
+ http_server_properties.GetAlternativeServices(http_host_port_pair);
+ EXPECT_TRUE(alternative_service_vector.empty());
+}
+
TEST_P(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeader) {
session_deps_.next_protos = SpdyNextProtos();
session_deps_.use_alternative_services = true;
@@ -8845,9 +8905,11 @@ TEST_P(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeader) {
EXPECT_EQ(1234, alternative_service_vector[1].port);
}
+// Alternate Protocol headers must be honored even if |use_alternative_services|
+// is false.
TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
session_deps_.next_protos = SpdyNextProtos();
- session_deps_.use_alternative_services = true;
+ session_deps_.use_alternative_services = false;
std::string alternate_protocol_http_header =
GetAlternateProtocolHttpHeader();
@@ -9031,6 +9093,50 @@ TEST_P(HttpNetworkTransactionTest, AltSvcOverwritesAlternateProtocol) {
EXPECT_EQ(443, alternative_service_vector[0].port);
}
+// When |use_alternative_services| is false, do not observe alternative service
+// entries that point to a different host.
+TEST_P(HttpNetworkTransactionTest, DisableAlternativeServiceToDifferentHost) {
+ session_deps_.use_alternative_services = false;
+
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("http://www.example.org/");
+ request.load_flags = 0;
+
+ MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
+ StaticSocketDataProvider first_data;
+ first_data.set_connect_data(mock_connect);
+ session_deps_.socket_factory->AddSocketDataProvider(&first_data);
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
+ MockRead(ASYNC, OK),
+ };
+ StaticSocketDataProvider second_data(data_reads, arraysize(data_reads),
+ nullptr, 0);
+ session_deps_.socket_factory->AddSocketDataProvider(&second_data);
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+
+ base::WeakPtr<HttpServerProperties> http_server_properties =
+ session->http_server_properties();
+ AlternativeService alternative_service(
+ AlternateProtocolFromNextProto(GetParam()), "different.example.org", 80);
+ base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
+ http_server_properties->SetAlternativeService(
+ HostPortPair::FromURL(request.url), alternative_service, 1.0, expiration);
+
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
+ TestCompletionCallback callback;
+
+ int rv = trans->Start(&request, callback.callback(), BoundNetLog());
+ // The connetion to origin was refused, and the alternative service should not
+ // be used (even though mock data are there), therefore the request should
+ // fail.
+ EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.GetResult(rv));
+}
+
TEST_P(HttpNetworkTransactionTest,
MarkBrokenAlternateProtocolAndFallback) {
session_deps_.use_alternative_services = true;
diff --git a/net/http/http_stream_factory_impl.cc b/net/http/http_stream_factory_impl.cc
index 68eb6af..2a8664e 100644
--- a/net/http/http_stream_factory_impl.cc
+++ b/net/http/http_stream_factory_impl.cc
@@ -152,9 +152,6 @@ const HostMappingRules* HttpStreamFactoryImpl::GetHostMappingRules() const {
AlternativeServiceVector HttpStreamFactoryImpl::GetAlternativeServicesFor(
const GURL& original_url) {
- if (!session_->params().use_alternative_services)
- return AlternativeServiceVector();
-
if (original_url.SchemeIs("ftp"))
return AlternativeServiceVector();
@@ -166,6 +163,9 @@ AlternativeServiceVector HttpStreamFactoryImpl::GetAlternativeServicesFor(
if (alternative_service_vector.empty())
return AlternativeServiceVector();
+ const bool enable_different_host =
+ session_->params().use_alternative_services;
+
AlternativeServiceVector enabled_alternative_service_vector;
for (const AlternativeService& alternative_service :
alternative_service_vector) {
@@ -176,6 +176,9 @@ AlternativeServiceVector HttpStreamFactoryImpl::GetAlternativeServicesFor(
continue;
}
+ if (origin.host() != alternative_service.host && !enable_different_host)
+ continue;
+
// Some shared unix systems may have user home directories (like
// http://foo.com/~mike) which allow users to emit headers. This is a bad
// idea already, but with Alternate-Protocol, it provides the ability for a