Index: net/http/http_network_transaction.cc |
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc |
index 04b341a835d4aabb0a2d5691e96b212d1a6e9656..1a2c9a0a2b4593c0dacb668f02791ad5b48bc0ec 100644 |
--- a/net/http/http_network_transaction.cc |
+++ b/net/http/http_network_transaction.cc |
@@ -4,11 +4,11 @@ |
#include "net/http/http_network_transaction.h" |
+#include "base/format_macros.h" |
+#include "base/scoped_ptr.h" |
#include "base/compiler_specific.h" |
#include "base/field_trial.h" |
-#include "base/format_macros.h" |
#include "base/histogram.h" |
-#include "base/scoped_ptr.h" |
#include "base/stats_counters.h" |
#include "base/string_util.h" |
#include "base/trace_event.h" |
@@ -25,7 +25,6 @@ |
#include "net/http/http_basic_stream.h" |
#include "net/http/http_chunked_decoder.h" |
#include "net/http/http_network_session.h" |
-#include "net/http/http_request_headers.h" |
#include "net/http/http_request_info.h" |
#include "net/http/http_response_headers.h" |
#include "net/http/http_response_info.h" |
@@ -47,112 +46,97 @@ namespace { |
const std::string* g_next_protos = NULL; |
void BuildRequestHeaders(const HttpRequestInfo* request_info, |
- const HttpRequestHeaders& authorization_headers, |
+ const std::string& authorization_headers, |
const UploadDataStream* upload_data_stream, |
bool using_proxy, |
- HttpRequestHeaders* request_headers) { |
+ std::string* request_headers) { |
+ // Headers that will be stripped from request_info->extra_headers to prevent, |
+ // e.g., plugins from overriding headers that are controlled using other |
+ // means. Otherwise a plugin could set a referrer although sending the |
+ // referrer is inhibited. |
+ // TODO(jochen): check whether also other headers should be stripped. |
+ static const char* const kExtraHeadersToBeStripped[] = { |
+ "Referer" |
+ }; |
+ |
const std::string path = using_proxy ? |
HttpUtil::SpecForRequest(request_info->url) : |
HttpUtil::PathForRequest(request_info->url); |
- request_headers->SetRequestLine( |
- request_info->method, path, "1.1"); |
- |
- request_headers->SetHeader(HttpRequestHeaders::kHost, |
- GetHostAndOptionalPort(request_info->url)); |
+ *request_headers = |
+ StringPrintf("%s %s HTTP/1.1\r\nHost: %s\r\n", |
+ request_info->method.c_str(), path.c_str(), |
+ GetHostAndOptionalPort(request_info->url).c_str()); |
// For compat with HTTP/1.0 servers and proxies: |
- if (using_proxy) { |
- request_headers->SetHeader(HttpRequestHeaders::kProxyConnection, |
- "keep-alive"); |
- } else { |
- request_headers->SetHeader(HttpRequestHeaders::kConnection, "keep-alive"); |
- } |
+ if (using_proxy) |
+ *request_headers += "Proxy-"; |
+ *request_headers += "Connection: keep-alive\r\n"; |
if (!request_info->user_agent.empty()) { |
- request_headers->SetHeader(HttpRequestHeaders::kUserAgent, |
- request_info->user_agent); |
+ StringAppendF(request_headers, "User-Agent: %s\r\n", |
+ request_info->user_agent.c_str()); |
} |
// Our consumer should have made sure that this is a safe referrer. See for |
// instance WebCore::FrameLoader::HideReferrer. |
- if (request_info->referrer.is_valid()) { |
- request_headers->SetHeader(HttpRequestHeaders::kReferer, |
- request_info->referrer.spec()); |
- } |
+ if (request_info->referrer.is_valid()) |
+ StringAppendF(request_headers, "Referer: %s\r\n", |
+ request_info->referrer.spec().c_str()); |
// Add a content length header? |
if (upload_data_stream) { |
- request_headers->SetHeader( |
- HttpRequestHeaders::kContentLength, |
- Uint64ToString(upload_data_stream->size())); |
+ StringAppendF(request_headers, "Content-Length: %" PRIu64 "\r\n", |
+ upload_data_stream->size()); |
} else if (request_info->method == "POST" || request_info->method == "PUT" || |
request_info->method == "HEAD") { |
// An empty POST/PUT request still needs a content length. As for HEAD, |
// IE and Safari also add a content length header. Presumably it is to |
// support sending a HEAD request to an URL that only expects to be sent a |
// POST or some other method that normally would have a message body. |
- request_headers->SetHeader(HttpRequestHeaders::kContentLength, "0"); |
+ *request_headers += "Content-Length: 0\r\n"; |
} |
// Honor load flags that impact proxy caches. |
if (request_info->load_flags & LOAD_BYPASS_CACHE) { |
- request_headers->SetHeader(HttpRequestHeaders::kPragma, "no-cache"); |
- request_headers->SetHeader(HttpRequestHeaders::kCacheControl, "no-cache"); |
+ *request_headers += "Pragma: no-cache\r\nCache-Control: no-cache\r\n"; |
} else if (request_info->load_flags & LOAD_VALIDATE_CACHE) { |
- request_headers->SetHeader(HttpRequestHeaders::kCacheControl, "max-age=0"); |
+ *request_headers += "Cache-Control: max-age=0\r\n"; |
} |
- request_headers->MergeFrom(authorization_headers); |
- |
- // Headers that will be stripped from request_info->extra_headers to prevent, |
- // e.g., plugins from overriding headers that are controlled using other |
- // means. Otherwise a plugin could set a referrer although sending the |
- // referrer is inhibited. |
- // TODO(jochen): check whether also other headers should be stripped. |
- static const char* const kExtraHeadersToBeStripped[] = { |
- "Referer" |
- }; |
- |
- // TODO(willchan): Change HttpRequestInfo::extra_headers to be a |
- // HttpRequestHeaders. |
- |
- std::vector<std::string> extra_headers_vector; |
- Tokenize(request_info->extra_headers, "\r\n", &extra_headers_vector); |
- HttpRequestHeaders extra_headers; |
- if (!extra_headers_vector.empty()) { |
- for (std::vector<std::string>::const_iterator it = |
- extra_headers_vector.begin(); it != extra_headers_vector.end(); ++it) |
- extra_headers.AddHeaderFromString(*it); |
+ if (!authorization_headers.empty()) { |
+ *request_headers += authorization_headers; |
+ } |
- for (size_t i = 0; i < arraysize(kExtraHeadersToBeStripped); ++i) |
- extra_headers.RemoveHeader(kExtraHeadersToBeStripped[i]); |
+ // TODO(darin): Need to prune out duplicate headers. |
- request_headers->MergeFrom(extra_headers); |
- } |
+ *request_headers += HttpUtil::StripHeaders(request_info->extra_headers, |
+ kExtraHeadersToBeStripped, arraysize(kExtraHeadersToBeStripped)); |
+ *request_headers += "\r\n"; |
} |
// The HTTP CONNECT method for establishing a tunnel connection is documented |
// in draft-luotonen-web-proxy-tunneling-01.txt and RFC 2817, Sections 5.2 and |
// 5.3. |
void BuildTunnelRequest(const HttpRequestInfo* request_info, |
- const HttpRequestHeaders& authorization_headers, |
- HttpRequestHeaders* request_headers) { |
+ const std::string& authorization_headers, |
+ std::string* request_headers) { |
// RFC 2616 Section 9 says the Host request-header field MUST accompany all |
// HTTP/1.1 requests. Add "Proxy-Connection: keep-alive" for compat with |
// HTTP/1.0 proxies such as Squid (required for NTLM authentication). |
- request_headers->SetRequestLine( |
- "CONNECT", GetHostAndPort(request_info->url), "1.1"); |
- request_headers->SetHeader(HttpRequestHeaders::kHost, |
- GetHostAndOptionalPort(request_info->url)); |
- request_headers->SetHeader(HttpRequestHeaders::kProxyConnection, |
- "keep-alive"); |
+ *request_headers = StringPrintf( |
+ "CONNECT %s HTTP/1.1\r\nHost: %s\r\nProxy-Connection: keep-alive\r\n", |
+ GetHostAndPort(request_info->url).c_str(), |
+ GetHostAndOptionalPort(request_info->url).c_str()); |
- if (!request_info->user_agent.empty()) { |
- request_headers->SetHeader(HttpRequestHeaders::kUserAgent, |
- request_info->user_agent); |
+ if (!request_info->user_agent.empty()) |
+ StringAppendF(request_headers, "User-Agent: %s\r\n", |
+ request_info->user_agent.c_str()); |
+ |
+ if (!authorization_headers.empty()) { |
+ *request_headers += authorization_headers; |
} |
- request_headers->MergeFrom(authorization_headers); |
+ *request_headers += "\r\n"; |
} |
void ProcessAlternateProtocol(const HttpResponseHeaders& headers, |
@@ -920,25 +904,24 @@ int HttpNetworkTransaction::DoSendRequest() { |
(HaveAuth(HttpAuth::AUTH_SERVER) || |
SelectPreemptiveAuth(HttpAuth::AUTH_SERVER)); |
- HttpRequestHeaders request_headers; |
- HttpRequestHeaders authorization_headers; |
+ std::string authorization_headers; |
// TODO(wtc): If BuildAuthorizationHeader fails (returns an authorization |
// header with no credentials), we should return an error to prevent |
// entering an infinite auth restart loop. See http://crbug.com/21050. |
if (have_proxy_auth) |
- AddAuthorizationHeader(HttpAuth::AUTH_PROXY, &authorization_headers); |
+ authorization_headers.append( |
+ BuildAuthorizationHeader(HttpAuth::AUTH_PROXY)); |
if (have_server_auth) |
- AddAuthorizationHeader(HttpAuth::AUTH_SERVER, &authorization_headers); |
+ authorization_headers.append( |
+ BuildAuthorizationHeader(HttpAuth::AUTH_SERVER)); |
if (establishing_tunnel_) { |
- BuildTunnelRequest(request_, authorization_headers, &request_headers); |
+ BuildTunnelRequest(request_, authorization_headers, &request_headers_); |
} else { |
BuildRequestHeaders(request_, authorization_headers, request_body, |
- proxy_mode_ == kHTTPProxy, &request_headers); |
+ proxy_mode_ == kHTTPProxy, &request_headers_); |
} |
- |
- request_headers_ = request_headers.ToString(); |
} |
headers_valid_ = false; |
@@ -1612,8 +1595,8 @@ bool HttpNetworkTransaction::ShouldApplyServerAuth() const { |
!(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA); |
} |
-void HttpNetworkTransaction::AddAuthorizationHeader( |
- HttpAuth::Target target, HttpRequestHeaders* authorization_headers) const { |
+std::string HttpNetworkTransaction::BuildAuthorizationHeader( |
+ HttpAuth::Target target) const { |
DCHECK(HaveAuth(target)); |
// Add a Authorization/Proxy-Authorization header line. |
@@ -1624,14 +1607,14 @@ void HttpNetworkTransaction::AddAuthorizationHeader( |
request_, |
&proxy_info_, |
&auth_token); |
- if (rv == OK) { |
- authorization_headers->SetHeader( |
- HttpAuth::GetAuthorizationHeaderName(target), auth_token); |
- } |
+ if (rv == OK) |
+ return HttpAuth::GetAuthorizationHeaderName(target) + |
+ ": " + auth_token + "\r\n"; |
// TODO(cbentzel): Evict username and password from cache on non-OK return? |
// TODO(cbentzel): Never use this scheme again if |
// ERR_UNSUPPORTED_AUTH_SCHEME is returned. |
+ return std::string(); |
} |
GURL HttpNetworkTransaction::AuthOrigin(HttpAuth::Target target) const { |