xref: /aosp_15_r20/external/cronet/net/http/proxy_client_socket.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 The Chromium Authors
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 <unordered_set>
8 
9 #include "base/metrics/histogram_macros.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "net/base/host_port_pair.h"
13 #include "net/base/net_errors.h"
14 #include "net/http/http_auth_controller.h"
15 #include "net/http/http_request_info.h"
16 #include "net/http/http_response_headers.h"
17 #include "net/http/http_response_info.h"
18 #include "url/gurl.h"
19 
20 namespace net {
21 
SetStreamPriority(RequestPriority priority)22 void ProxyClientSocket::SetStreamPriority(RequestPriority priority) {}
23 
24 // static
BuildTunnelRequest(const HostPortPair & endpoint,const HttpRequestHeaders & extra_headers,const std::string & user_agent,std::string * request_line,HttpRequestHeaders * request_headers)25 void ProxyClientSocket::BuildTunnelRequest(
26     const HostPortPair& endpoint,
27     const HttpRequestHeaders& extra_headers,
28     const std::string& user_agent,
29     std::string* request_line,
30     HttpRequestHeaders* request_headers) {
31   // RFC 7230 Section 5.4 says a client MUST send a Host header field in all
32   // HTTP/1.1 request messages, and Host SHOULD be the first header field
33   // following the request-line.  Add "Proxy-Connection: keep-alive" for compat
34   // with HTTP/1.0 proxies such as Squid (required for NTLM authentication).
35   std::string host_and_port = endpoint.ToString();
36   *request_line =
37       base::StringPrintf("CONNECT %s HTTP/1.1\r\n", host_and_port.c_str());
38   request_headers->SetHeader(HttpRequestHeaders::kHost, host_and_port);
39   request_headers->SetHeader(HttpRequestHeaders::kProxyConnection,
40                              "keep-alive");
41   if (!user_agent.empty())
42     request_headers->SetHeader(HttpRequestHeaders::kUserAgent, user_agent);
43 
44   request_headers->MergeFrom(extra_headers);
45 }
46 
47 // static
HandleProxyAuthChallenge(HttpAuthController * auth,HttpResponseInfo * response,const NetLogWithSource & net_log)48 int ProxyClientSocket::HandleProxyAuthChallenge(
49     HttpAuthController* auth,
50     HttpResponseInfo* response,
51     const NetLogWithSource& net_log) {
52   DCHECK(response->headers.get());
53   int rv = auth->HandleAuthChallenge(response->headers, response->ssl_info,
54                                      false, true, net_log);
55   auth->TakeAuthInfo(&response->auth_challenge);
56   if (rv == OK)
57     return ERR_PROXY_AUTH_REQUESTED;
58   return rv;
59 }
60 
61 // static
SanitizeProxyAuth(HttpResponseInfo & response)62 void ProxyClientSocket::SanitizeProxyAuth(HttpResponseInfo& response) {
63   DCHECK(response.headers);
64 
65   // Copy status line and all hop-by-hop headers to preserve keep-alive
66   // behavior.
67   const char* kHeadersToKeep[] = {
68       "connection",         "proxy-connection", "keep-alive", "trailer",
69       "transfer-encoding",  "upgrade",
70 
71       "content-length",
72 
73       "proxy-authenticate",
74   };
75 
76   // Create a list of all present header not in |kHeadersToKeep|, and then
77   // remove them.
78   size_t iter = 0;
79   std::string header_name;
80   std::string header_value;
81   std::unordered_set<std::string> headers_to_remove;
82   while (response.headers->EnumerateHeaderLines(&iter, &header_name,
83                                                 &header_value)) {
84     bool remove = true;
85     for (const char* header : kHeadersToKeep) {
86       if (base::EqualsCaseInsensitiveASCII(header, header_name)) {
87         remove = false;
88         break;
89       }
90     }
91     if (remove)
92       headers_to_remove.insert(header_name);
93   }
94 
95   response.headers->RemoveHeaders(headers_to_remove);
96 }
97 
98 }  // namespace net
99