Chromium Code Reviews

Side by Side Diff: net/http/http_network_transaction.cc

Issue 1110014: Reland r42300: "HttpRequestHeaders refactor."" (Closed)
Patch Set: Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/http/http_network_transaction.h" 5 #include "net/http/http_network_transaction.h"
6 6
7 #include "base/format_macros.h"
8 #include "base/scoped_ptr.h"
9 #include "base/compiler_specific.h" 7 #include "base/compiler_specific.h"
10 #include "base/field_trial.h" 8 #include "base/field_trial.h"
9 #include "base/format_macros.h"
11 #include "base/histogram.h" 10 #include "base/histogram.h"
11 #include "base/scoped_ptr.h"
12 #include "base/stats_counters.h" 12 #include "base/stats_counters.h"
13 #include "base/string_util.h" 13 #include "base/string_util.h"
14 #include "base/trace_event.h" 14 #include "base/trace_event.h"
15 #include "build/build_config.h" 15 #include "build/build_config.h"
16 #include "net/base/connection_type_histograms.h" 16 #include "net/base/connection_type_histograms.h"
17 #include "net/base/io_buffer.h" 17 #include "net/base/io_buffer.h"
18 #include "net/base/load_flags.h" 18 #include "net/base/load_flags.h"
19 #include "net/base/net_errors.h" 19 #include "net/base/net_errors.h"
20 #include "net/base/net_util.h" 20 #include "net/base/net_util.h"
21 #include "net/base/ssl_cert_request_info.h" 21 #include "net/base/ssl_cert_request_info.h"
22 #include "net/base/upload_data_stream.h" 22 #include "net/base/upload_data_stream.h"
23 #include "net/http/http_auth.h" 23 #include "net/http/http_auth.h"
24 #include "net/http/http_auth_handler.h" 24 #include "net/http/http_auth_handler.h"
25 #include "net/http/http_basic_stream.h" 25 #include "net/http/http_basic_stream.h"
26 #include "net/http/http_chunked_decoder.h" 26 #include "net/http/http_chunked_decoder.h"
27 #include "net/http/http_network_session.h" 27 #include "net/http/http_network_session.h"
28 #include "net/http/http_request_headers.h"
28 #include "net/http/http_request_info.h" 29 #include "net/http/http_request_info.h"
29 #include "net/http/http_response_headers.h" 30 #include "net/http/http_response_headers.h"
30 #include "net/http/http_response_info.h" 31 #include "net/http/http_response_info.h"
31 #include "net/http/http_util.h" 32 #include "net/http/http_util.h"
32 #include "net/socket/client_socket_factory.h" 33 #include "net/socket/client_socket_factory.h"
33 #include "net/socket/socks_client_socket_pool.h" 34 #include "net/socket/socks_client_socket_pool.h"
34 #include "net/socket/ssl_client_socket.h" 35 #include "net/socket/ssl_client_socket.h"
35 #include "net/socket/tcp_client_socket_pool.h" 36 #include "net/socket/tcp_client_socket_pool.h"
36 #include "net/spdy/spdy_session.h" 37 #include "net/spdy/spdy_session.h"
37 #include "net/spdy/spdy_session_pool.h" 38 #include "net/spdy/spdy_session_pool.h"
38 #include "net/spdy/spdy_stream.h" 39 #include "net/spdy/spdy_stream.h"
39 40
40 using base::Time; 41 using base::Time;
41 42
42 namespace net { 43 namespace net {
43 44
44 namespace { 45 namespace {
45 46
46 const std::string* g_next_protos = NULL; 47 const std::string* g_next_protos = NULL;
47 48
48 void BuildRequestHeaders(const HttpRequestInfo* request_info, 49 void BuildRequestHeaders(const HttpRequestInfo* request_info,
49 const std::string& authorization_headers, 50 const HttpRequestHeaders& authorization_headers,
50 const UploadDataStream* upload_data_stream, 51 const UploadDataStream* upload_data_stream,
51 bool using_proxy, 52 bool using_proxy,
52 std::string* request_headers) { 53 HttpRequestHeaders* request_headers) {
54 const std::string path = using_proxy ?
55 HttpUtil::SpecForRequest(request_info->url) :
56 HttpUtil::PathForRequest(request_info->url);
57 request_headers->SetRequestLine(
58 request_info->method, path, "1.1");
59
60 request_headers->SetHeader(HttpRequestHeaders::kHost,
61 GetHostAndOptionalPort(request_info->url));
62
63 // For compat with HTTP/1.0 servers and proxies:
64 if (using_proxy) {
65 request_headers->SetHeader(HttpRequestHeaders::kProxyConnection,
66 "keep-alive");
67 } else {
68 request_headers->SetHeader(HttpRequestHeaders::kConnection, "keep-alive");
69 }
70
71 if (!request_info->user_agent.empty()) {
72 request_headers->SetHeader(HttpRequestHeaders::kUserAgent,
73 request_info->user_agent);
74 }
75
76 // Our consumer should have made sure that this is a safe referrer. See for
77 // instance WebCore::FrameLoader::HideReferrer.
78 if (request_info->referrer.is_valid()) {
79 request_headers->SetHeader(HttpRequestHeaders::kReferer,
80 request_info->referrer.spec());
81 }
82
83 // Add a content length header?
84 if (upload_data_stream) {
85 request_headers->SetHeader(
86 HttpRequestHeaders::kContentLength,
87 Uint64ToString(upload_data_stream->size()));
88 } else if (request_info->method == "POST" || request_info->method == "PUT" ||
89 request_info->method == "HEAD") {
90 // An empty POST/PUT request still needs a content length. As for HEAD,
91 // IE and Safari also add a content length header. Presumably it is to
92 // support sending a HEAD request to an URL that only expects to be sent a
93 // POST or some other method that normally would have a message body.
94 request_headers->SetHeader(HttpRequestHeaders::kContentLength, "0");
95 }
96
97 // Honor load flags that impact proxy caches.
98 if (request_info->load_flags & LOAD_BYPASS_CACHE) {
99 request_headers->SetHeader(HttpRequestHeaders::kPragma, "no-cache");
100 request_headers->SetHeader(HttpRequestHeaders::kCacheControl, "no-cache");
101 } else if (request_info->load_flags & LOAD_VALIDATE_CACHE) {
102 request_headers->SetHeader(HttpRequestHeaders::kCacheControl, "max-age=0");
103 }
104
105 request_headers->MergeFrom(authorization_headers);
106
53 // Headers that will be stripped from request_info->extra_headers to prevent, 107 // Headers that will be stripped from request_info->extra_headers to prevent,
54 // e.g., plugins from overriding headers that are controlled using other 108 // e.g., plugins from overriding headers that are controlled using other
55 // means. Otherwise a plugin could set a referrer although sending the 109 // means. Otherwise a plugin could set a referrer although sending the
56 // referrer is inhibited. 110 // referrer is inhibited.
57 // TODO(jochen): check whether also other headers should be stripped. 111 // TODO(jochen): check whether also other headers should be stripped.
58 static const char* const kExtraHeadersToBeStripped[] = { 112 static const char* const kExtraHeadersToBeStripped[] = {
59 "Referer" 113 "Referer"
60 }; 114 };
61 115
62 const std::string path = using_proxy ? 116 // TODO(willchan): Change HttpRequestInfo::extra_headers to be a
63 HttpUtil::SpecForRequest(request_info->url) : 117 // HttpRequestHeaders.
64 HttpUtil::PathForRequest(request_info->url);
65 *request_headers =
66 StringPrintf("%s %s HTTP/1.1\r\nHost: %s\r\n",
67 request_info->method.c_str(), path.c_str(),
68 GetHostAndOptionalPort(request_info->url).c_str());
69 118
70 // For compat with HTTP/1.0 servers and proxies: 119 std::vector<std::string> extra_headers_vector;
71 if (using_proxy) 120 Tokenize(request_info->extra_headers, "\r\n", &extra_headers_vector);
72 *request_headers += "Proxy-"; 121 HttpRequestHeaders extra_headers;
73 *request_headers += "Connection: keep-alive\r\n"; 122 if (!extra_headers_vector.empty()) {
123 for (std::vector<std::string>::const_iterator it =
124 extra_headers_vector.begin(); it != extra_headers_vector.end(); ++it)
125 extra_headers.AddHeaderFromString(*it);
74 126
75 if (!request_info->user_agent.empty()) { 127 for (size_t i = 0; i < arraysize(kExtraHeadersToBeStripped); ++i)
76 StringAppendF(request_headers, "User-Agent: %s\r\n", 128 extra_headers.RemoveHeader(kExtraHeadersToBeStripped[i]);
77 request_info->user_agent.c_str()); 129
130 request_headers->MergeFrom(extra_headers);
78 } 131 }
79
80 // Our consumer should have made sure that this is a safe referrer. See for
81 // instance WebCore::FrameLoader::HideReferrer.
82 if (request_info->referrer.is_valid())
83 StringAppendF(request_headers, "Referer: %s\r\n",
84 request_info->referrer.spec().c_str());
85
86 // Add a content length header?
87 if (upload_data_stream) {
88 StringAppendF(request_headers, "Content-Length: %" PRIu64 "\r\n",
89 upload_data_stream->size());
90 } else if (request_info->method == "POST" || request_info->method == "PUT" ||
91 request_info->method == "HEAD") {
92 // An empty POST/PUT request still needs a content length. As for HEAD,
93 // IE and Safari also add a content length header. Presumably it is to
94 // support sending a HEAD request to an URL that only expects to be sent a
95 // POST or some other method that normally would have a message body.
96 *request_headers += "Content-Length: 0\r\n";
97 }
98
99 // Honor load flags that impact proxy caches.
100 if (request_info->load_flags & LOAD_BYPASS_CACHE) {
101 *request_headers += "Pragma: no-cache\r\nCache-Control: no-cache\r\n";
102 } else if (request_info->load_flags & LOAD_VALIDATE_CACHE) {
103 *request_headers += "Cache-Control: max-age=0\r\n";
104 }
105
106 if (!authorization_headers.empty()) {
107 *request_headers += authorization_headers;
108 }
109
110 // TODO(darin): Need to prune out duplicate headers.
111
112 *request_headers += HttpUtil::StripHeaders(request_info->extra_headers,
113 kExtraHeadersToBeStripped, arraysize(kExtraHeadersToBeStripped));
114 *request_headers += "\r\n";
115 } 132 }
116 133
117 // The HTTP CONNECT method for establishing a tunnel connection is documented 134 // The HTTP CONNECT method for establishing a tunnel connection is documented
118 // in draft-luotonen-web-proxy-tunneling-01.txt and RFC 2817, Sections 5.2 and 135 // in draft-luotonen-web-proxy-tunneling-01.txt and RFC 2817, Sections 5.2 and
119 // 5.3. 136 // 5.3.
120 void BuildTunnelRequest(const HttpRequestInfo* request_info, 137 void BuildTunnelRequest(const HttpRequestInfo* request_info,
121 const std::string& authorization_headers, 138 const HttpRequestHeaders& authorization_headers,
122 std::string* request_headers) { 139 HttpRequestHeaders* request_headers) {
123 // RFC 2616 Section 9 says the Host request-header field MUST accompany all 140 // RFC 2616 Section 9 says the Host request-header field MUST accompany all
124 // HTTP/1.1 requests. Add "Proxy-Connection: keep-alive" for compat with 141 // HTTP/1.1 requests. Add "Proxy-Connection: keep-alive" for compat with
125 // HTTP/1.0 proxies such as Squid (required for NTLM authentication). 142 // HTTP/1.0 proxies such as Squid (required for NTLM authentication).
126 *request_headers = StringPrintf( 143 request_headers->SetRequestLine(
127 "CONNECT %s HTTP/1.1\r\nHost: %s\r\nProxy-Connection: keep-alive\r\n", 144 "CONNECT", GetHostAndPort(request_info->url), "1.1");
128 GetHostAndPort(request_info->url).c_str(), 145 request_headers->SetHeader(HttpRequestHeaders::kHost,
129 GetHostAndOptionalPort(request_info->url).c_str()); 146 GetHostAndOptionalPort(request_info->url));
147 request_headers->SetHeader(HttpRequestHeaders::kProxyConnection,
148 "keep-alive");
130 149
131 if (!request_info->user_agent.empty()) 150 if (!request_info->user_agent.empty()) {
132 StringAppendF(request_headers, "User-Agent: %s\r\n", 151 request_headers->SetHeader(HttpRequestHeaders::kUserAgent,
133 request_info->user_agent.c_str()); 152 request_info->user_agent);
134
135 if (!authorization_headers.empty()) {
136 *request_headers += authorization_headers;
137 } 153 }
138 154
139 *request_headers += "\r\n"; 155 request_headers->MergeFrom(authorization_headers);
140 } 156 }
141 157
142 void ProcessAlternateProtocol(const HttpResponseHeaders& headers, 158 void ProcessAlternateProtocol(const HttpResponseHeaders& headers,
143 const HostPortPair& http_host_port_pair, 159 const HostPortPair& http_host_port_pair,
144 HttpAlternateProtocols* alternate_protocols) { 160 HttpAlternateProtocols* alternate_protocols) {
145 if (!g_next_protos || g_next_protos->empty()) { 161 if (!g_next_protos || g_next_protos->empty()) {
146 // This implies that NPN is not suppoted. We don't currently support any 162 // This implies that NPN is not suppoted. We don't currently support any
147 // alternate protocols that don't use NPN. 163 // alternate protocols that don't use NPN.
148 return; 164 return;
149 } 165 }
(...skipping 747 matching lines...)
897 // headers. 913 // headers.
898 bool have_proxy_auth = 914 bool have_proxy_auth =
899 ShouldApplyProxyAuth() && 915 ShouldApplyProxyAuth() &&
900 (HaveAuth(HttpAuth::AUTH_PROXY) || 916 (HaveAuth(HttpAuth::AUTH_PROXY) ||
901 SelectPreemptiveAuth(HttpAuth::AUTH_PROXY)); 917 SelectPreemptiveAuth(HttpAuth::AUTH_PROXY));
902 bool have_server_auth = 918 bool have_server_auth =
903 ShouldApplyServerAuth() && 919 ShouldApplyServerAuth() &&
904 (HaveAuth(HttpAuth::AUTH_SERVER) || 920 (HaveAuth(HttpAuth::AUTH_SERVER) ||
905 SelectPreemptiveAuth(HttpAuth::AUTH_SERVER)); 921 SelectPreemptiveAuth(HttpAuth::AUTH_SERVER));
906 922
907 std::string authorization_headers; 923 HttpRequestHeaders request_headers;
924 HttpRequestHeaders authorization_headers;
908 925
909 // TODO(wtc): If BuildAuthorizationHeader fails (returns an authorization 926 // TODO(wtc): If BuildAuthorizationHeader fails (returns an authorization
910 // header with no credentials), we should return an error to prevent 927 // header with no credentials), we should return an error to prevent
911 // entering an infinite auth restart loop. See http://crbug.com/21050. 928 // entering an infinite auth restart loop. See http://crbug.com/21050.
912 if (have_proxy_auth) 929 if (have_proxy_auth)
913 authorization_headers.append( 930 AddAuthorizationHeader(HttpAuth::AUTH_PROXY, &authorization_headers);
914 BuildAuthorizationHeader(HttpAuth::AUTH_PROXY));
915 if (have_server_auth) 931 if (have_server_auth)
916 authorization_headers.append( 932 AddAuthorizationHeader(HttpAuth::AUTH_SERVER, &authorization_headers);
917 BuildAuthorizationHeader(HttpAuth::AUTH_SERVER));
918 933
919 if (establishing_tunnel_) { 934 if (establishing_tunnel_) {
920 BuildTunnelRequest(request_, authorization_headers, &request_headers_); 935 BuildTunnelRequest(request_, authorization_headers, &request_headers);
921 } else { 936 } else {
922 BuildRequestHeaders(request_, authorization_headers, request_body, 937 BuildRequestHeaders(request_, authorization_headers, request_body,
923 proxy_mode_ == kHTTPProxy, &request_headers_); 938 proxy_mode_ == kHTTPProxy, &request_headers);
924 } 939 }
940
941 request_headers_ = request_headers.ToString();
925 } 942 }
926 943
927 headers_valid_ = false; 944 headers_valid_ = false;
928 http_stream_.reset(new HttpBasicStream(connection_.get(), net_log_)); 945 http_stream_.reset(new HttpBasicStream(connection_.get(), net_log_));
929 946
930 return http_stream_->SendRequest(request_, request_headers_, 947 return http_stream_->SendRequest(request_, request_headers_,
931 request_body, &response_, &io_callback_); 948 request_body, &response_, &io_callback_);
932 } 949 }
933 950
934 int HttpNetworkTransaction::DoSendRequestComplete(int result) { 951 int HttpNetworkTransaction::DoSendRequestComplete(int result) {
(...skipping 653 matching lines...)
1588 1605
1589 bool HttpNetworkTransaction::ShouldApplyProxyAuth() const { 1606 bool HttpNetworkTransaction::ShouldApplyProxyAuth() const {
1590 return (proxy_mode_ == kHTTPProxy) || establishing_tunnel_; 1607 return (proxy_mode_ == kHTTPProxy) || establishing_tunnel_;
1591 } 1608 }
1592 1609
1593 bool HttpNetworkTransaction::ShouldApplyServerAuth() const { 1610 bool HttpNetworkTransaction::ShouldApplyServerAuth() const {
1594 return !establishing_tunnel_ && 1611 return !establishing_tunnel_ &&
1595 !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA); 1612 !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA);
1596 } 1613 }
1597 1614
1598 std::string HttpNetworkTransaction::BuildAuthorizationHeader( 1615 void HttpNetworkTransaction::AddAuthorizationHeader(
1599 HttpAuth::Target target) const { 1616 HttpAuth::Target target, HttpRequestHeaders* authorization_headers) const {
1600 DCHECK(HaveAuth(target)); 1617 DCHECK(HaveAuth(target));
1601 1618
1602 // Add a Authorization/Proxy-Authorization header line. 1619 // Add a Authorization/Proxy-Authorization header line.
1603 std::string auth_token; 1620 std::string auth_token;
1604 int rv = auth_handler_[target]->GenerateAuthToken( 1621 int rv = auth_handler_[target]->GenerateAuthToken(
1605 auth_identity_[target].username, 1622 auth_identity_[target].username,
1606 auth_identity_[target].password, 1623 auth_identity_[target].password,
1607 request_, 1624 request_,
1608 &proxy_info_, 1625 &proxy_info_,
1609 &auth_token); 1626 &auth_token);
1610 if (rv == OK) 1627 if (rv == OK) {
1611 return HttpAuth::GetAuthorizationHeaderName(target) + 1628 authorization_headers->SetHeader(
1612 ": " + auth_token + "\r\n"; 1629 HttpAuth::GetAuthorizationHeaderName(target), auth_token);
1630 }
1613 1631
1614 // TODO(cbentzel): Evict username and password from cache on non-OK return? 1632 // TODO(cbentzel): Evict username and password from cache on non-OK return?
1615 // TODO(cbentzel): Never use this scheme again if 1633 // TODO(cbentzel): Never use this scheme again if
1616 // ERR_UNSUPPORTED_AUTH_SCHEME is returned. 1634 // ERR_UNSUPPORTED_AUTH_SCHEME is returned.
1617 return std::string();
1618 } 1635 }
1619 1636
1620 GURL HttpNetworkTransaction::AuthOrigin(HttpAuth::Target target) const { 1637 GURL HttpNetworkTransaction::AuthOrigin(HttpAuth::Target target) const {
1621 return target == HttpAuth::AUTH_PROXY ? 1638 return target == HttpAuth::AUTH_PROXY ?
1622 GURL("http://" + proxy_info_.proxy_server().host_and_port()) : 1639 GURL("http://" + proxy_info_.proxy_server().host_and_port()) :
1623 request_->url.GetOrigin(); 1640 request_->url.GetOrigin();
1624 } 1641 }
1625 1642
1626 std::string HttpNetworkTransaction::AuthPath(HttpAuth::Target target) 1643 std::string HttpNetworkTransaction::AuthPath(HttpAuth::Target target)
1627 const { 1644 const {
(...skipping 245 matching lines...)
1873 http_host_port_pair); 1890 http_host_port_pair);
1874 1891
1875 alternate_protocol_mode_ = kDoNotUseAlternateProtocol; 1892 alternate_protocol_mode_ = kDoNotUseAlternateProtocol;
1876 if (connection_->socket()) 1893 if (connection_->socket())
1877 connection_->socket()->Disconnect(); 1894 connection_->socket()->Disconnect();
1878 connection_->Reset(); 1895 connection_->Reset();
1879 next_state_ = STATE_INIT_CONNECTION; 1896 next_state_ = STATE_INIT_CONNECTION;
1880 } 1897 }
1881 1898
1882 } // namespace net 1899 } // namespace net
OLDNEW

Powered by Google App Engine