| OLD | NEW |
| 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/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
| 8 #include "base/field_trial.h" | 8 #include "base/field_trial.h" |
| 9 #include "base/format_macros.h" | 9 #include "base/format_macros.h" |
| 10 #include "base/histogram.h" | 10 #include "base/histogram.h" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 namespace net { | 44 namespace net { |
| 45 | 45 |
| 46 namespace { | 46 namespace { |
| 47 | 47 |
| 48 const std::string* g_next_protos = NULL; | 48 const std::string* g_next_protos = NULL; |
| 49 | 49 |
| 50 void BuildRequestHeaders(const HttpRequestInfo* request_info, | 50 void BuildRequestHeaders(const HttpRequestInfo* request_info, |
| 51 const HttpRequestHeaders& authorization_headers, | 51 const HttpRequestHeaders& authorization_headers, |
| 52 const UploadDataStream* upload_data_stream, | 52 const UploadDataStream* upload_data_stream, |
| 53 bool using_proxy, | 53 bool using_proxy, |
| 54 std::string* request_line, |
| 54 HttpRequestHeaders* request_headers) { | 55 HttpRequestHeaders* request_headers) { |
| 55 const std::string path = using_proxy ? | 56 const std::string path = using_proxy ? |
| 56 HttpUtil::SpecForRequest(request_info->url) : | 57 HttpUtil::SpecForRequest(request_info->url) : |
| 57 HttpUtil::PathForRequest(request_info->url); | 58 HttpUtil::PathForRequest(request_info->url); |
| 58 request_headers->SetRequestLine( | 59 *request_line = StringPrintf( |
| 59 request_info->method, path, "1.1"); | 60 "%s %s HTTP/1.1\r\n", request_info->method.c_str(), path.c_str()); |
| 60 | |
| 61 request_headers->SetHeader(HttpRequestHeaders::kHost, | 61 request_headers->SetHeader(HttpRequestHeaders::kHost, |
| 62 GetHostAndOptionalPort(request_info->url)); | 62 GetHostAndOptionalPort(request_info->url)); |
| 63 | 63 |
| 64 // For compat with HTTP/1.0 servers and proxies: | 64 // For compat with HTTP/1.0 servers and proxies: |
| 65 if (using_proxy) { | 65 if (using_proxy) { |
| 66 request_headers->SetHeader(HttpRequestHeaders::kProxyConnection, | 66 request_headers->SetHeader(HttpRequestHeaders::kProxyConnection, |
| 67 "keep-alive"); | 67 "keep-alive"); |
| 68 } else { | 68 } else { |
| 69 request_headers->SetHeader(HttpRequestHeaders::kConnection, "keep-alive"); | 69 request_headers->SetHeader(HttpRequestHeaders::kConnection, "keep-alive"); |
| 70 } | 70 } |
| 71 | 71 |
| 72 if (!request_info->user_agent.empty()) { | |
| 73 request_headers->SetHeader(HttpRequestHeaders::kUserAgent, | |
| 74 request_info->user_agent); | |
| 75 } | |
| 76 | |
| 77 // Our consumer should have made sure that this is a safe referrer. See for | 72 // Our consumer should have made sure that this is a safe referrer. See for |
| 78 // instance WebCore::FrameLoader::HideReferrer. | 73 // instance WebCore::FrameLoader::HideReferrer. |
| 79 if (request_info->referrer.is_valid()) { | 74 if (request_info->referrer.is_valid()) { |
| 80 request_headers->SetHeader(HttpRequestHeaders::kReferer, | 75 request_headers->SetHeader(HttpRequestHeaders::kReferer, |
| 81 request_info->referrer.spec()); | 76 request_info->referrer.spec()); |
| 82 } | 77 } |
| 83 | 78 |
| 84 // Add a content length header? | 79 // Add a content length header? |
| 85 if (upload_data_stream) { | 80 if (upload_data_stream) { |
| 86 request_headers->SetHeader( | 81 request_headers->SetHeader( |
| (...skipping 20 matching lines...) Expand all Loading... |
| 107 | 102 |
| 108 // Headers that will be stripped from request_info->extra_headers to prevent, | 103 // Headers that will be stripped from request_info->extra_headers to prevent, |
| 109 // e.g., plugins from overriding headers that are controlled using other | 104 // e.g., plugins from overriding headers that are controlled using other |
| 110 // means. Otherwise a plugin could set a referrer although sending the | 105 // means. Otherwise a plugin could set a referrer although sending the |
| 111 // referrer is inhibited. | 106 // referrer is inhibited. |
| 112 // TODO(jochen): check whether also other headers should be stripped. | 107 // TODO(jochen): check whether also other headers should be stripped. |
| 113 static const char* const kExtraHeadersToBeStripped[] = { | 108 static const char* const kExtraHeadersToBeStripped[] = { |
| 114 "Referer" | 109 "Referer" |
| 115 }; | 110 }; |
| 116 | 111 |
| 117 // TODO(willchan): Change HttpRequestInfo::extra_headers to be a | 112 HttpRequestHeaders stripped_extra_headers; |
| 118 // HttpRequestHeaders. | 113 stripped_extra_headers.CopyFrom(request_info->extra_headers); |
| 119 | |
| 120 std::vector<std::string> extra_headers_vector; | |
| 121 Tokenize(request_info->extra_headers, "\r\n", &extra_headers_vector); | |
| 122 HttpRequestHeaders extra_headers; | |
| 123 if (!extra_headers_vector.empty()) { | |
| 124 for (std::vector<std::string>::const_iterator it = | |
| 125 extra_headers_vector.begin(); it != extra_headers_vector.end(); ++it) | |
| 126 extra_headers.AddHeaderFromString(*it); | |
| 127 | |
| 128 for (size_t i = 0; i < arraysize(kExtraHeadersToBeStripped); ++i) | 114 for (size_t i = 0; i < arraysize(kExtraHeadersToBeStripped); ++i) |
| 129 extra_headers.RemoveHeader(kExtraHeadersToBeStripped[i]); | 115 stripped_extra_headers.RemoveHeader(kExtraHeadersToBeStripped[i]); |
| 130 | 116 request_headers->MergeFrom(stripped_extra_headers); |
| 131 request_headers->MergeFrom(extra_headers); | |
| 132 } | |
| 133 } | 117 } |
| 134 | 118 |
| 135 // The HTTP CONNECT method for establishing a tunnel connection is documented | 119 // The HTTP CONNECT method for establishing a tunnel connection is documented |
| 136 // in draft-luotonen-web-proxy-tunneling-01.txt and RFC 2817, Sections 5.2 and | 120 // in draft-luotonen-web-proxy-tunneling-01.txt and RFC 2817, Sections 5.2 and |
| 137 // 5.3. | 121 // 5.3. |
| 138 void BuildTunnelRequest(const HttpRequestInfo* request_info, | 122 void BuildTunnelRequest(const HttpRequestInfo* request_info, |
| 139 const HttpRequestHeaders& authorization_headers, | 123 const HttpRequestHeaders& authorization_headers, |
| 124 std::string* request_line, |
| 140 HttpRequestHeaders* request_headers) { | 125 HttpRequestHeaders* request_headers) { |
| 141 // RFC 2616 Section 9 says the Host request-header field MUST accompany all | 126 // RFC 2616 Section 9 says the Host request-header field MUST accompany all |
| 142 // HTTP/1.1 requests. Add "Proxy-Connection: keep-alive" for compat with | 127 // HTTP/1.1 requests. Add "Proxy-Connection: keep-alive" for compat with |
| 143 // HTTP/1.0 proxies such as Squid (required for NTLM authentication). | 128 // HTTP/1.0 proxies such as Squid (required for NTLM authentication). |
| 144 request_headers->SetRequestLine( | 129 *request_line = StringPrintf( |
| 145 "CONNECT", GetHostAndPort(request_info->url), "1.1"); | 130 "CONNECT %s HTTP/1.1\r\n", GetHostAndPort(request_info->url).c_str()); |
| 146 request_headers->SetHeader(HttpRequestHeaders::kHost, | 131 request_headers->SetHeader(HttpRequestHeaders::kHost, |
| 147 GetHostAndOptionalPort(request_info->url)); | 132 GetHostAndOptionalPort(request_info->url)); |
| 148 request_headers->SetHeader(HttpRequestHeaders::kProxyConnection, | 133 request_headers->SetHeader(HttpRequestHeaders::kProxyConnection, |
| 149 "keep-alive"); | 134 "keep-alive"); |
| 150 | 135 |
| 151 if (!request_info->user_agent.empty()) { | 136 std::string user_agent; |
| 152 request_headers->SetHeader(HttpRequestHeaders::kUserAgent, | 137 if (request_info->extra_headers.GetHeader(HttpRequestHeaders::kUserAgent, |
| 153 request_info->user_agent); | 138 &user_agent)) |
| 154 } | 139 request_headers->SetHeader(HttpRequestHeaders::kUserAgent, user_agent); |
| 155 | 140 |
| 156 request_headers->MergeFrom(authorization_headers); | 141 request_headers->MergeFrom(authorization_headers); |
| 157 } | 142 } |
| 158 | 143 |
| 159 void ProcessAlternateProtocol(const HttpResponseHeaders& headers, | 144 void ProcessAlternateProtocol(const HttpResponseHeaders& headers, |
| 160 const HostPortPair& http_host_port_pair, | 145 const HostPortPair& http_host_port_pair, |
| 161 HttpAlternateProtocols* alternate_protocols) { | 146 HttpAlternateProtocols* alternate_protocols) { |
| 162 if (!g_next_protos || g_next_protos->empty()) { | 147 if (!g_next_protos || g_next_protos->empty()) { |
| 163 // This implies that NPN is not suppoted. We don't currently support any | 148 // This implies that NPN is not suppoted. We don't currently support any |
| 164 // alternate protocols that don't use NPN. | 149 // alternate protocols that don't use NPN. |
| (...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 924 // headers. | 909 // headers. |
| 925 bool have_proxy_auth = | 910 bool have_proxy_auth = |
| 926 ShouldApplyProxyAuth() && | 911 ShouldApplyProxyAuth() && |
| 927 (HaveAuth(HttpAuth::AUTH_PROXY) || | 912 (HaveAuth(HttpAuth::AUTH_PROXY) || |
| 928 SelectPreemptiveAuth(HttpAuth::AUTH_PROXY)); | 913 SelectPreemptiveAuth(HttpAuth::AUTH_PROXY)); |
| 929 bool have_server_auth = | 914 bool have_server_auth = |
| 930 ShouldApplyServerAuth() && | 915 ShouldApplyServerAuth() && |
| 931 (HaveAuth(HttpAuth::AUTH_SERVER) || | 916 (HaveAuth(HttpAuth::AUTH_SERVER) || |
| 932 SelectPreemptiveAuth(HttpAuth::AUTH_SERVER)); | 917 SelectPreemptiveAuth(HttpAuth::AUTH_SERVER)); |
| 933 | 918 |
| 919 std::string request_line; |
| 934 HttpRequestHeaders request_headers; | 920 HttpRequestHeaders request_headers; |
| 935 HttpRequestHeaders authorization_headers; | 921 HttpRequestHeaders authorization_headers; |
| 936 | 922 |
| 937 // TODO(wtc): If BuildAuthorizationHeader fails (returns an authorization | 923 // TODO(wtc): If BuildAuthorizationHeader fails (returns an authorization |
| 938 // header with no credentials), we should return an error to prevent | 924 // header with no credentials), we should return an error to prevent |
| 939 // entering an infinite auth restart loop. See http://crbug.com/21050. | 925 // entering an infinite auth restart loop. See http://crbug.com/21050. |
| 940 if (have_proxy_auth) | 926 if (have_proxy_auth) |
| 941 AddAuthorizationHeader(HttpAuth::AUTH_PROXY, &authorization_headers); | 927 AddAuthorizationHeader(HttpAuth::AUTH_PROXY, &authorization_headers); |
| 942 if (have_server_auth) | 928 if (have_server_auth) |
| 943 AddAuthorizationHeader(HttpAuth::AUTH_SERVER, &authorization_headers); | 929 AddAuthorizationHeader(HttpAuth::AUTH_SERVER, &authorization_headers); |
| 944 | 930 |
| 945 if (establishing_tunnel_) { | 931 if (establishing_tunnel_) { |
| 946 BuildTunnelRequest(request_, authorization_headers, &request_headers); | 932 BuildTunnelRequest(request_, authorization_headers, &request_line, |
| 933 &request_headers); |
| 947 } else { | 934 } else { |
| 948 BuildRequestHeaders(request_, authorization_headers, request_body, | 935 BuildRequestHeaders(request_, authorization_headers, request_body, |
| 949 proxy_mode_ == kHTTPProxy, &request_headers); | 936 proxy_mode_ == kHTTPProxy, &request_line, |
| 937 &request_headers); |
| 950 } | 938 } |
| 951 | 939 |
| 952 request_headers_ = request_headers.ToString(); | 940 request_headers_ = request_line + request_headers.ToString(); |
| 953 } | 941 } |
| 954 | 942 |
| 955 headers_valid_ = false; | 943 headers_valid_ = false; |
| 956 http_stream_.reset(new HttpBasicStream(connection_.get(), net_log_)); | 944 http_stream_.reset(new HttpBasicStream(connection_.get(), net_log_)); |
| 957 | 945 |
| 958 return http_stream_->SendRequest(request_, request_headers_, | 946 return http_stream_->SendRequest(request_, request_headers_, |
| 959 request_body, &response_, &io_callback_); | 947 request_body, &response_, &io_callback_); |
| 960 } | 948 } |
| 961 | 949 |
| 962 int HttpNetworkTransaction::DoSendRequestComplete(int result) { | 950 int HttpNetworkTransaction::DoSendRequestComplete(int result) { |
| (...skipping 980 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1943 http_host_port_pair); | 1931 http_host_port_pair); |
| 1944 | 1932 |
| 1945 alternate_protocol_mode_ = kDoNotUseAlternateProtocol; | 1933 alternate_protocol_mode_ = kDoNotUseAlternateProtocol; |
| 1946 if (connection_->socket()) | 1934 if (connection_->socket()) |
| 1947 connection_->socket()->Disconnect(); | 1935 connection_->socket()->Disconnect(); |
| 1948 connection_->Reset(); | 1936 connection_->Reset(); |
| 1949 next_state_ = STATE_INIT_CONNECTION; | 1937 next_state_ = STATE_INIT_CONNECTION; |
| 1950 } | 1938 } |
| 1951 | 1939 |
| 1952 } // namespace net | 1940 } // namespace net |
| OLD | NEW |