diff options
Diffstat (limited to 'net/http/http_network_transaction.cc')
-rw-r--r-- | net/http/http_network_transaction.cc | 143 |
1 files changed, 80 insertions, 63 deletions
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index 57cf773..f3f4a7d 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,6 +25,7 @@ #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,97 +48,112 @@ namespace { const std::string* g_next_protos = NULL; void BuildRequestHeaders(const HttpRequestInfo* request_info, - const std::string& authorization_headers, + const HttpRequestHeaders& authorization_headers, const UploadDataStream* upload_data_stream, bool using_proxy, - 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" - }; - + HttpRequestHeaders* request_headers) { const std::string path = using_proxy ? HttpUtil::SpecForRequest(request_info->url) : HttpUtil::PathForRequest(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()); + request_headers->SetRequestLine( + request_info->method, path, "1.1"); + + request_headers->SetHeader(HttpRequestHeaders::kHost, + GetHostAndOptionalPort(request_info->url)); // For compat with HTTP/1.0 servers and proxies: - if (using_proxy) - *request_headers += "Proxy-"; - *request_headers += "Connection: keep-alive\r\n"; + if (using_proxy) { + request_headers->SetHeader(HttpRequestHeaders::kProxyConnection, + "keep-alive"); + } else { + request_headers->SetHeader(HttpRequestHeaders::kConnection, "keep-alive"); + } if (!request_info->user_agent.empty()) { - StringAppendF(request_headers, "User-Agent: %s\r\n", - request_info->user_agent.c_str()); + request_headers->SetHeader(HttpRequestHeaders::kUserAgent, + request_info->user_agent); } // Our consumer should have made sure that this is a safe referrer. See for // instance WebCore::FrameLoader::HideReferrer. - if (request_info->referrer.is_valid()) - StringAppendF(request_headers, "Referer: %s\r\n", - request_info->referrer.spec().c_str()); + if (request_info->referrer.is_valid()) { + request_headers->SetHeader(HttpRequestHeaders::kReferer, + request_info->referrer.spec()); + } // Add a content length header? if (upload_data_stream) { - StringAppendF(request_headers, "Content-Length: %" PRIu64 "\r\n", - upload_data_stream->size()); + request_headers->SetHeader( + HttpRequestHeaders::kContentLength, + Uint64ToString(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 += "Content-Length: 0\r\n"; + request_headers->SetHeader(HttpRequestHeaders::kContentLength, "0"); } // Honor load flags that impact proxy caches. if (request_info->load_flags & LOAD_BYPASS_CACHE) { - *request_headers += "Pragma: no-cache\r\nCache-Control: no-cache\r\n"; + request_headers->SetHeader(HttpRequestHeaders::kPragma, "no-cache"); + request_headers->SetHeader(HttpRequestHeaders::kCacheControl, "no-cache"); } else if (request_info->load_flags & LOAD_VALIDATE_CACHE) { - *request_headers += "Cache-Control: max-age=0\r\n"; + request_headers->SetHeader(HttpRequestHeaders::kCacheControl, "max-age=0"); } - if (!authorization_headers.empty()) { - *request_headers += authorization_headers; - } + request_headers->MergeFrom(authorization_headers); - // TODO(darin): Need to prune out duplicate 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" + }; - *request_headers += HttpUtil::StripHeaders(request_info->extra_headers, - kExtraHeadersToBeStripped, arraysize(kExtraHeadersToBeStripped)); - *request_headers += "\r\n"; + // 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); + + for (size_t i = 0; i < arraysize(kExtraHeadersToBeStripped); ++i) + extra_headers.RemoveHeader(kExtraHeadersToBeStripped[i]); + + request_headers->MergeFrom(extra_headers); + } } // 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 std::string& authorization_headers, - std::string* request_headers) { + const HttpRequestHeaders& authorization_headers, + HttpRequestHeaders* 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 = 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()); + 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"); - 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; + if (!request_info->user_agent.empty()) { + request_headers->SetHeader(HttpRequestHeaders::kUserAgent, + request_info->user_agent); } - *request_headers += "\r\n"; + request_headers->MergeFrom(authorization_headers); } void ProcessAlternateProtocol(const HttpResponseHeaders& headers, @@ -915,24 +931,25 @@ int HttpNetworkTransaction::DoSendRequest() { (HaveAuth(HttpAuth::AUTH_SERVER) || SelectPreemptiveAuth(HttpAuth::AUTH_SERVER)); - std::string authorization_headers; + HttpRequestHeaders request_headers; + HttpRequestHeaders 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) - authorization_headers.append( - BuildAuthorizationHeader(HttpAuth::AUTH_PROXY)); + AddAuthorizationHeader(HttpAuth::AUTH_PROXY, &authorization_headers); if (have_server_auth) - authorization_headers.append( - BuildAuthorizationHeader(HttpAuth::AUTH_SERVER)); + AddAuthorizationHeader(HttpAuth::AUTH_SERVER, &authorization_headers); 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; @@ -1611,8 +1628,8 @@ bool HttpNetworkTransaction::ShouldApplyServerAuth() const { !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA); } -std::string HttpNetworkTransaction::BuildAuthorizationHeader( - HttpAuth::Target target) const { +void HttpNetworkTransaction::AddAuthorizationHeader( + HttpAuth::Target target, HttpRequestHeaders* authorization_headers) const { DCHECK(HaveAuth(target)); // Add a Authorization/Proxy-Authorization header line. @@ -1628,14 +1645,14 @@ std::string HttpNetworkTransaction::BuildAuthorizationHeader( auth_identity_[target].password, request_, &proxy_info_, &auth_token); } - if (rv == OK) - return HttpAuth::GetAuthorizationHeaderName(target) + - ": " + auth_token + "\r\n"; + if (rv == OK) { + authorization_headers->SetHeader( + HttpAuth::GetAuthorizationHeaderName(target), auth_token); + } // 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 { |