1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/http/http_stream_factory.h"
7 #include "base/logging.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_split.h"
10 #include "base/strings/string_util.h"
11 #include "base/time/time.h"
12 #include "net/base/host_mapping_rules.h"
13 #include "net/base/host_port_pair.h"
14 #include "net/base/port_util.h"
15 #include "net/http/http_network_session.h"
16 #include "net/spdy/spdy_alt_svc_wire_format.h"
21 // WARNING: If you modify or add any static flags, you must keep them in sync
22 // with |ResetStaticSettingsToInit|. This is critical for unit test isolation.
25 bool HttpStreamFactory::spdy_enabled_
= true;
27 HttpStreamFactory::~HttpStreamFactory() {}
30 void HttpStreamFactory::ResetStaticSettingsToInit() {
34 void HttpStreamFactory::ProcessAlternativeService(
35 const base::WeakPtr
<HttpServerProperties
>& http_server_properties
,
36 base::StringPiece alternative_service_str
,
37 const HostPortPair
& http_host_port_pair
,
38 const HttpNetworkSession
& session
) {
39 SpdyAltSvcWireFormat::AlternativeServiceVector alternative_service_vector
;
40 if (!SpdyAltSvcWireFormat::ParseHeaderFieldValue(
41 alternative_service_str
, &alternative_service_vector
)) {
45 // Convert SpdyAltSvcWireFormat::AlternativeService entries
46 // to net::AlternativeServiceInfo.
47 AlternativeServiceInfoVector alternative_service_info_vector
;
48 for (const SpdyAltSvcWireFormat::AlternativeService
&
49 alternative_service_entry
: alternative_service_vector
) {
50 AlternateProtocol protocol
=
51 AlternateProtocolFromString(alternative_service_entry
.protocol_id
);
52 if (!IsAlternateProtocolValid(protocol
) ||
53 !session
.IsProtocolEnabled(protocol
) ||
54 !IsPortValid(alternative_service_entry
.port
)) {
57 AlternativeService
alternative_service(protocol
,
58 alternative_service_entry
.host
,
59 alternative_service_entry
.port
);
60 base::Time expiration
=
62 base::TimeDelta::FromSeconds(alternative_service_entry
.max_age
);
63 AlternativeServiceInfo
alternative_service_info(
64 alternative_service
, alternative_service_entry
.p
, expiration
);
65 alternative_service_info_vector
.push_back(alternative_service_info
);
68 http_server_properties
->SetAlternativeServices(
69 RewriteHost(http_host_port_pair
), alternative_service_info_vector
);
72 void HttpStreamFactory::ProcessAlternateProtocol(
73 const base::WeakPtr
<HttpServerProperties
>& http_server_properties
,
74 const std::vector
<std::string
>& alternate_protocol_values
,
75 const HostPortPair
& http_host_port_pair
,
76 const HttpNetworkSession
& session
) {
77 AlternateProtocol protocol
= UNINITIALIZED_ALTERNATE_PROTOCOL
;
79 double probability
= 1;
81 for (size_t i
= 0; i
< alternate_protocol_values
.size(); ++i
) {
82 base::StringPiece alternate_protocol_str
= alternate_protocol_values
[i
];
83 if (base::StartsWith(alternate_protocol_str
, "p=",
84 base::CompareCase::SENSITIVE
)) {
85 if (!base::StringToDouble(alternate_protocol_str
.substr(2).as_string(),
87 probability
< 0 || probability
> 1) {
88 DVLOG(1) << kAlternateProtocolHeader
89 << " header has unrecognizable probability: "
90 << alternate_protocol_values
[i
];
97 std::vector
<base::StringPiece
> port_protocol_vector
=
98 base::SplitStringPiece(alternate_protocol_str
, ":",
99 base::TRIM_WHITESPACE
, base::SPLIT_WANT_ALL
);
100 if (port_protocol_vector
.size() != 2) {
101 DVLOG(1) << kAlternateProtocolHeader
102 << " header has too many tokens: "
103 << alternate_protocol_str
;
108 if (!base::StringToInt(port_protocol_vector
[0], &port
) ||
109 port
== 0 || !IsPortValid(port
)) {
110 DVLOG(1) << kAlternateProtocolHeader
111 << " header has unrecognizable port: "
112 << port_protocol_vector
[0];
117 protocol
= AlternateProtocolFromString(port_protocol_vector
[1].as_string());
119 if (IsAlternateProtocolValid(protocol
) &&
120 !session
.IsProtocolEnabled(protocol
)) {
121 DVLOG(1) << kAlternateProtocolHeader
122 << " header has unrecognized protocol: "
123 << port_protocol_vector
[1];
129 if (!is_valid
|| protocol
== UNINITIALIZED_ALTERNATE_PROTOCOL
) {
130 http_server_properties
->ClearAlternativeServices(http_host_port_pair
);
134 http_server_properties
->SetAlternativeService(
135 RewriteHost(http_host_port_pair
),
136 AlternativeService(protocol
, "", static_cast<uint16
>(port
)), probability
,
137 base::Time::Now() + base::TimeDelta::FromDays(1));
140 GURL
HttpStreamFactory::ApplyHostMappingRules(const GURL
& url
,
141 HostPortPair
* endpoint
) {
142 const HostMappingRules
* mapping_rules
= GetHostMappingRules();
143 if (mapping_rules
&& mapping_rules
->RewriteHost(endpoint
)) {
144 url::Replacements
<char> replacements
;
145 const std::string port_str
= base::UintToString(endpoint
->port());
146 replacements
.SetPort(port_str
.c_str(), url::Component(0, port_str
.size()));
147 replacements
.SetHost(endpoint
->host().c_str(),
148 url::Component(0, endpoint
->host().size()));
149 return url
.ReplaceComponents(replacements
);
154 HttpStreamFactory::HttpStreamFactory() {}
156 HostPortPair
HttpStreamFactory::RewriteHost(HostPortPair host_port_pair
) {
157 const HostMappingRules
* mapping_rules
= GetHostMappingRules();
159 mapping_rules
->RewriteHost(&host_port_pair
);
160 return host_port_pair
;