• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "net/http/proxy_client_socket.h"
6 
7 #include "base/metrics/histogram.h"
8 #include "base/strings/stringprintf.h"
9 #include "net/base/host_port_pair.h"
10 #include "net/base/net_errors.h"
11 #include "net/base/net_util.h"
12 #include "net/http/http_auth_controller.h"
13 #include "net/http/http_request_info.h"
14 #include "net/http/http_response_headers.h"
15 #include "net/http/http_response_info.h"
16 #include "url/gurl.h"
17 
18 namespace net {
19 
20 // static
BuildTunnelRequest(const HttpRequestInfo & request_info,const HttpRequestHeaders & auth_headers,const HostPortPair & endpoint,std::string * request_line,HttpRequestHeaders * request_headers)21 void ProxyClientSocket::BuildTunnelRequest(
22     const HttpRequestInfo& request_info,
23     const HttpRequestHeaders& auth_headers,
24     const HostPortPair& endpoint,
25     std::string* request_line,
26     HttpRequestHeaders* request_headers) {
27   // RFC 2616 Section 9 says the Host request-header field MUST accompany all
28   // HTTP/1.1 requests.  Add "Proxy-Connection: keep-alive" for compat with
29   // HTTP/1.0 proxies such as Squid (required for NTLM authentication).
30   *request_line = base::StringPrintf(
31       "CONNECT %s HTTP/1.1\r\n", endpoint.ToString().c_str());
32   request_headers->SetHeader(HttpRequestHeaders::kHost,
33                              GetHostAndOptionalPort(request_info.url));
34   request_headers->SetHeader(HttpRequestHeaders::kProxyConnection,
35                              "keep-alive");
36 
37   std::string user_agent;
38   if (request_info.extra_headers.GetHeader(HttpRequestHeaders::kUserAgent,
39                                             &user_agent))
40     request_headers->SetHeader(HttpRequestHeaders::kUserAgent, user_agent);
41 
42   request_headers->MergeFrom(auth_headers);
43 }
44 
45 // static
HandleProxyAuthChallenge(HttpAuthController * auth,HttpResponseInfo * response,const BoundNetLog & net_log)46 int ProxyClientSocket::HandleProxyAuthChallenge(HttpAuthController* auth,
47                                                 HttpResponseInfo* response,
48                                                 const BoundNetLog& net_log) {
49   DCHECK(response->headers.get());
50   int rv = auth->HandleAuthChallenge(response->headers, false, true, net_log);
51   response->auth_challenge = auth->auth_info();
52   if (rv == OK)
53     return ERR_PROXY_AUTH_REQUESTED;
54   return rv;
55 }
56 
57 // static
LogBlockedTunnelResponse(int http_status_code,const GURL & url,bool is_https_proxy)58 void ProxyClientSocket::LogBlockedTunnelResponse(int http_status_code,
59                                                  const GURL& url,
60                                                  bool is_https_proxy) {
61   if (is_https_proxy) {
62     UMA_HISTOGRAM_CUSTOM_ENUMERATION(
63         "Net.BlockedTunnelResponse.HttpsProxy",
64         HttpUtil::MapStatusCodeForHistogram(http_status_code),
65         HttpUtil::GetStatusCodesForHistogram());
66   } else {
67     UMA_HISTOGRAM_CUSTOM_ENUMERATION(
68         "Net.BlockedTunnelResponse.HttpProxy",
69         HttpUtil::MapStatusCodeForHistogram(http_status_code),
70         HttpUtil::GetStatusCodesForHistogram());
71   }
72 }
73 
74 // static
SanitizeProxyRedirect(HttpResponseInfo * response,const GURL & url)75 bool ProxyClientSocket::SanitizeProxyRedirect(HttpResponseInfo* response,
76                                               const GURL& url) {
77   DCHECK(response && response->headers.get());
78 
79   std::string location;
80   if (!response->headers->IsRedirect(&location))
81     return false;
82 
83   // Return minimal headers; set "Content-length: 0" to ignore response body.
84   std::string fake_response_headers =
85       base::StringPrintf("HTTP/1.0 302 Found\n"
86                          "Location: %s\n"
87                          "Content-length: 0\n"
88                          "Connection: close\n"
89                          "\n",
90                          location.c_str());
91   std::string raw_headers =
92       HttpUtil::AssembleRawHeaders(fake_response_headers.data(),
93                                    fake_response_headers.length());
94   response->headers = new HttpResponseHeaders(raw_headers);
95 
96   return true;
97 }
98 
99 }  // namespace net
100