xref: /aosp_15_r20/external/cronet/net/http/http_request_headers.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "net/http/http_request_headers.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <string_view>
8*6777b538SAndroid Build Coastguard Worker #include <utility>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_macros.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/strings/escape.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/strings/strcat.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_split.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/values.h"
19*6777b538SAndroid Build Coastguard Worker #include "net/base/url_util.h"
20*6777b538SAndroid Build Coastguard Worker #include "net/http/http_log_util.h"
21*6777b538SAndroid Build Coastguard Worker #include "net/http/http_util.h"
22*6777b538SAndroid Build Coastguard Worker #include "net/log/net_log_capture_mode.h"
23*6777b538SAndroid Build Coastguard Worker #include "net/log/net_log_values.h"
24*6777b538SAndroid Build Coastguard Worker 
25*6777b538SAndroid Build Coastguard Worker namespace net {
26*6777b538SAndroid Build Coastguard Worker 
27*6777b538SAndroid Build Coastguard Worker namespace {
28*6777b538SAndroid Build Coastguard Worker 
SupportsStreamType(const std::optional<base::flat_set<SourceStream::SourceType>> & accepted_stream_types,SourceStream::SourceType type)29*6777b538SAndroid Build Coastguard Worker bool SupportsStreamType(
30*6777b538SAndroid Build Coastguard Worker     const std::optional<base::flat_set<SourceStream::SourceType>>&
31*6777b538SAndroid Build Coastguard Worker         accepted_stream_types,
32*6777b538SAndroid Build Coastguard Worker     SourceStream::SourceType type) {
33*6777b538SAndroid Build Coastguard Worker   if (!accepted_stream_types)
34*6777b538SAndroid Build Coastguard Worker     return true;
35*6777b538SAndroid Build Coastguard Worker   return accepted_stream_types->contains(type);
36*6777b538SAndroid Build Coastguard Worker }
37*6777b538SAndroid Build Coastguard Worker 
38*6777b538SAndroid Build Coastguard Worker }  // namespace
39*6777b538SAndroid Build Coastguard Worker 
40*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kConnectMethod[] = "CONNECT";
41*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kDeleteMethod[] = "DELETE";
42*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kGetMethod[] = "GET";
43*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kHeadMethod[] = "HEAD";
44*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kOptionsMethod[] = "OPTIONS";
45*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kPatchMethod[] = "PATCH";
46*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kPostMethod[] = "POST";
47*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kPutMethod[] = "PUT";
48*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kTraceMethod[] = "TRACE";
49*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kTrackMethod[] = "TRACK";
50*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kAccept[] = "Accept";
51*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kAcceptCharset[] = "Accept-Charset";
52*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kAcceptEncoding[] = "Accept-Encoding";
53*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kAcceptLanguage[] = "Accept-Language";
54*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kAuthorization[] = "Authorization";
55*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kCacheControl[] = "Cache-Control";
56*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kConnection[] = "Connection";
57*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kContentLength[] = "Content-Length";
58*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kContentType[] = "Content-Type";
59*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kCookie[] = "Cookie";
60*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kHost[] = "Host";
61*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kIfMatch[] = "If-Match";
62*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kIfModifiedSince[] = "If-Modified-Since";
63*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kIfNoneMatch[] = "If-None-Match";
64*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kIfRange[] = "If-Range";
65*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kIfUnmodifiedSince[] = "If-Unmodified-Since";
66*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kOrigin[] = "Origin";
67*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kPragma[] = "Pragma";
68*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kPriority[] = "Priority";
69*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kProxyAuthorization[] = "Proxy-Authorization";
70*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kProxyConnection[] = "Proxy-Connection";
71*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kRange[] = "Range";
72*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kReferer[] = "Referer";
73*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kTransferEncoding[] = "Transfer-Encoding";
74*6777b538SAndroid Build Coastguard Worker const char HttpRequestHeaders::kUserAgent[] = "User-Agent";
75*6777b538SAndroid Build Coastguard Worker 
76*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders::HeaderKeyValuePair::HeaderKeyValuePair() = default;
77*6777b538SAndroid Build Coastguard Worker 
HeaderKeyValuePair(std::string_view key,std::string_view value)78*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders::HeaderKeyValuePair::HeaderKeyValuePair(
79*6777b538SAndroid Build Coastguard Worker     std::string_view key,
80*6777b538SAndroid Build Coastguard Worker     std::string_view value)
81*6777b538SAndroid Build Coastguard Worker     : HeaderKeyValuePair(key, std::string(value)) {}
82*6777b538SAndroid Build Coastguard Worker 
HeaderKeyValuePair(std::string_view key,std::string && value)83*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders::HeaderKeyValuePair::HeaderKeyValuePair(std::string_view key,
84*6777b538SAndroid Build Coastguard Worker                                                            std::string&& value)
85*6777b538SAndroid Build Coastguard Worker     : key(key), value(std::move(value)) {}
86*6777b538SAndroid Build Coastguard Worker 
Iterator(const HttpRequestHeaders & headers)87*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders::Iterator::Iterator(const HttpRequestHeaders& headers)
88*6777b538SAndroid Build Coastguard Worker     : curr_(headers.headers_.begin()), end_(headers.headers_.end()) {}
89*6777b538SAndroid Build Coastguard Worker 
90*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders::Iterator::~Iterator() = default;
91*6777b538SAndroid Build Coastguard Worker 
GetNext()92*6777b538SAndroid Build Coastguard Worker bool HttpRequestHeaders::Iterator::GetNext() {
93*6777b538SAndroid Build Coastguard Worker   if (!started_) {
94*6777b538SAndroid Build Coastguard Worker     started_ = true;
95*6777b538SAndroid Build Coastguard Worker     return curr_ != end_;
96*6777b538SAndroid Build Coastguard Worker   }
97*6777b538SAndroid Build Coastguard Worker 
98*6777b538SAndroid Build Coastguard Worker   if (curr_ == end_)
99*6777b538SAndroid Build Coastguard Worker     return false;
100*6777b538SAndroid Build Coastguard Worker 
101*6777b538SAndroid Build Coastguard Worker   ++curr_;
102*6777b538SAndroid Build Coastguard Worker   return curr_ != end_;
103*6777b538SAndroid Build Coastguard Worker }
104*6777b538SAndroid Build Coastguard Worker 
105*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders::HttpRequestHeaders() = default;
106*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders::HttpRequestHeaders(const HttpRequestHeaders& other) =
107*6777b538SAndroid Build Coastguard Worker     default;
108*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders::HttpRequestHeaders(HttpRequestHeaders&& other) = default;
109*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders::~HttpRequestHeaders() = default;
110*6777b538SAndroid Build Coastguard Worker 
111*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders& HttpRequestHeaders::operator=(
112*6777b538SAndroid Build Coastguard Worker     const HttpRequestHeaders& other) = default;
113*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders& HttpRequestHeaders::operator=(HttpRequestHeaders&& other) =
114*6777b538SAndroid Build Coastguard Worker     default;
115*6777b538SAndroid Build Coastguard Worker 
GetHeader(std::string_view key,std::string * out) const116*6777b538SAndroid Build Coastguard Worker bool HttpRequestHeaders::GetHeader(std::string_view key,
117*6777b538SAndroid Build Coastguard Worker                                    std::string* out) const {
118*6777b538SAndroid Build Coastguard Worker   auto it = FindHeader(key);
119*6777b538SAndroid Build Coastguard Worker   if (it == headers_.end())
120*6777b538SAndroid Build Coastguard Worker     return false;
121*6777b538SAndroid Build Coastguard Worker   out->assign(it->value);
122*6777b538SAndroid Build Coastguard Worker   return true;
123*6777b538SAndroid Build Coastguard Worker }
124*6777b538SAndroid Build Coastguard Worker 
Clear()125*6777b538SAndroid Build Coastguard Worker void HttpRequestHeaders::Clear() {
126*6777b538SAndroid Build Coastguard Worker   headers_.clear();
127*6777b538SAndroid Build Coastguard Worker }
128*6777b538SAndroid Build Coastguard Worker 
SetHeader(std::string_view key,std::string_view value)129*6777b538SAndroid Build Coastguard Worker void HttpRequestHeaders::SetHeader(std::string_view key,
130*6777b538SAndroid Build Coastguard Worker                                    std::string_view value) {
131*6777b538SAndroid Build Coastguard Worker   SetHeader(key, std::string(value));
132*6777b538SAndroid Build Coastguard Worker }
133*6777b538SAndroid Build Coastguard Worker 
SetHeader(std::string_view key,std::string && value)134*6777b538SAndroid Build Coastguard Worker void HttpRequestHeaders::SetHeader(std::string_view key, std::string&& value) {
135*6777b538SAndroid Build Coastguard Worker   // Invalid header names or values could mean clients can attach
136*6777b538SAndroid Build Coastguard Worker   // browser-internal headers.
137*6777b538SAndroid Build Coastguard Worker   CHECK(HttpUtil::IsValidHeaderName(key)) << key;
138*6777b538SAndroid Build Coastguard Worker   CHECK(HttpUtil::IsValidHeaderValue(value)) << key << " has invalid value.";
139*6777b538SAndroid Build Coastguard Worker 
140*6777b538SAndroid Build Coastguard Worker   SetHeaderInternal(key, std::move(value));
141*6777b538SAndroid Build Coastguard Worker }
142*6777b538SAndroid Build Coastguard Worker 
SetHeaderWithoutCheckForTesting(std::string_view key,std::string_view value)143*6777b538SAndroid Build Coastguard Worker void HttpRequestHeaders::SetHeaderWithoutCheckForTesting(
144*6777b538SAndroid Build Coastguard Worker     std::string_view key,
145*6777b538SAndroid Build Coastguard Worker     std::string_view value) {
146*6777b538SAndroid Build Coastguard Worker   SetHeaderInternal(key, std::string(value));
147*6777b538SAndroid Build Coastguard Worker }
148*6777b538SAndroid Build Coastguard Worker 
SetHeaderIfMissing(std::string_view key,std::string_view value)149*6777b538SAndroid Build Coastguard Worker void HttpRequestHeaders::SetHeaderIfMissing(std::string_view key,
150*6777b538SAndroid Build Coastguard Worker                                             std::string_view value) {
151*6777b538SAndroid Build Coastguard Worker   // Invalid header names or values could mean clients can attach
152*6777b538SAndroid Build Coastguard Worker   // browser-internal headers.
153*6777b538SAndroid Build Coastguard Worker   CHECK(HttpUtil::IsValidHeaderName(key));
154*6777b538SAndroid Build Coastguard Worker   CHECK(HttpUtil::IsValidHeaderValue(value));
155*6777b538SAndroid Build Coastguard Worker   auto it = FindHeader(key);
156*6777b538SAndroid Build Coastguard Worker   if (it == headers_.end())
157*6777b538SAndroid Build Coastguard Worker     headers_.push_back(HeaderKeyValuePair(key, value));
158*6777b538SAndroid Build Coastguard Worker }
159*6777b538SAndroid Build Coastguard Worker 
RemoveHeader(std::string_view key)160*6777b538SAndroid Build Coastguard Worker void HttpRequestHeaders::RemoveHeader(std::string_view key) {
161*6777b538SAndroid Build Coastguard Worker   auto it = FindHeader(key);
162*6777b538SAndroid Build Coastguard Worker   if (it != headers_.end())
163*6777b538SAndroid Build Coastguard Worker     headers_.erase(it);
164*6777b538SAndroid Build Coastguard Worker }
165*6777b538SAndroid Build Coastguard Worker 
AddHeaderFromString(std::string_view header_line)166*6777b538SAndroid Build Coastguard Worker void HttpRequestHeaders::AddHeaderFromString(std::string_view header_line) {
167*6777b538SAndroid Build Coastguard Worker   DCHECK_EQ(std::string::npos, header_line.find("\r\n"))
168*6777b538SAndroid Build Coastguard Worker       << "\"" << header_line << "\" contains CRLF.";
169*6777b538SAndroid Build Coastguard Worker 
170*6777b538SAndroid Build Coastguard Worker   const std::string::size_type key_end_index = header_line.find(":");
171*6777b538SAndroid Build Coastguard Worker   if (key_end_index == std::string::npos) {
172*6777b538SAndroid Build Coastguard Worker     LOG(DFATAL) << "\"" << header_line << "\" is missing colon delimiter.";
173*6777b538SAndroid Build Coastguard Worker     return;
174*6777b538SAndroid Build Coastguard Worker   }
175*6777b538SAndroid Build Coastguard Worker 
176*6777b538SAndroid Build Coastguard Worker   if (key_end_index == 0) {
177*6777b538SAndroid Build Coastguard Worker     LOG(DFATAL) << "\"" << header_line << "\" is missing header key.";
178*6777b538SAndroid Build Coastguard Worker     return;
179*6777b538SAndroid Build Coastguard Worker   }
180*6777b538SAndroid Build Coastguard Worker 
181*6777b538SAndroid Build Coastguard Worker   const std::string_view header_key(header_line.data(), key_end_index);
182*6777b538SAndroid Build Coastguard Worker   if (!HttpUtil::IsValidHeaderName(header_key)) {
183*6777b538SAndroid Build Coastguard Worker     LOG(DFATAL) << "\"" << header_line << "\" has invalid header key.";
184*6777b538SAndroid Build Coastguard Worker     return;
185*6777b538SAndroid Build Coastguard Worker   }
186*6777b538SAndroid Build Coastguard Worker 
187*6777b538SAndroid Build Coastguard Worker   const std::string::size_type value_index = key_end_index + 1;
188*6777b538SAndroid Build Coastguard Worker 
189*6777b538SAndroid Build Coastguard Worker   if (value_index < header_line.size()) {
190*6777b538SAndroid Build Coastguard Worker     std::string_view header_value(header_line.data() + value_index,
191*6777b538SAndroid Build Coastguard Worker                                   header_line.size() - value_index);
192*6777b538SAndroid Build Coastguard Worker     header_value = HttpUtil::TrimLWS(header_value);
193*6777b538SAndroid Build Coastguard Worker     if (!HttpUtil::IsValidHeaderValue(header_value)) {
194*6777b538SAndroid Build Coastguard Worker       LOG(DFATAL) << "\"" << header_line << "\" has invalid header value.";
195*6777b538SAndroid Build Coastguard Worker       return;
196*6777b538SAndroid Build Coastguard Worker     }
197*6777b538SAndroid Build Coastguard Worker     SetHeader(header_key, header_value);
198*6777b538SAndroid Build Coastguard Worker   } else if (value_index == header_line.size()) {
199*6777b538SAndroid Build Coastguard Worker     SetHeader(header_key, "");
200*6777b538SAndroid Build Coastguard Worker   } else {
201*6777b538SAndroid Build Coastguard Worker     NOTREACHED();
202*6777b538SAndroid Build Coastguard Worker   }
203*6777b538SAndroid Build Coastguard Worker }
204*6777b538SAndroid Build Coastguard Worker 
AddHeadersFromString(std::string_view headers)205*6777b538SAndroid Build Coastguard Worker void HttpRequestHeaders::AddHeadersFromString(std::string_view headers) {
206*6777b538SAndroid Build Coastguard Worker   for (std::string_view header : base::SplitStringPieceUsingSubstr(
207*6777b538SAndroid Build Coastguard Worker            headers, "\r\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
208*6777b538SAndroid Build Coastguard Worker     AddHeaderFromString(header);
209*6777b538SAndroid Build Coastguard Worker   }
210*6777b538SAndroid Build Coastguard Worker }
211*6777b538SAndroid Build Coastguard Worker 
MergeFrom(const HttpRequestHeaders & other)212*6777b538SAndroid Build Coastguard Worker void HttpRequestHeaders::MergeFrom(const HttpRequestHeaders& other) {
213*6777b538SAndroid Build Coastguard Worker   for (const auto& header : other.headers_) {
214*6777b538SAndroid Build Coastguard Worker     SetHeader(header.key, header.value);
215*6777b538SAndroid Build Coastguard Worker   }
216*6777b538SAndroid Build Coastguard Worker }
217*6777b538SAndroid Build Coastguard Worker 
ToString() const218*6777b538SAndroid Build Coastguard Worker std::string HttpRequestHeaders::ToString() const {
219*6777b538SAndroid Build Coastguard Worker   std::string output;
220*6777b538SAndroid Build Coastguard Worker   for (const auto& header : headers_) {
221*6777b538SAndroid Build Coastguard Worker     base::StringAppendF(&output, "%s: %s\r\n", header.key.c_str(),
222*6777b538SAndroid Build Coastguard Worker                         header.value.c_str());
223*6777b538SAndroid Build Coastguard Worker   }
224*6777b538SAndroid Build Coastguard Worker   output.append("\r\n");
225*6777b538SAndroid Build Coastguard Worker   return output;
226*6777b538SAndroid Build Coastguard Worker }
227*6777b538SAndroid Build Coastguard Worker 
NetLogParams(const std::string & request_line,NetLogCaptureMode capture_mode) const228*6777b538SAndroid Build Coastguard Worker base::Value::Dict HttpRequestHeaders::NetLogParams(
229*6777b538SAndroid Build Coastguard Worker     const std::string& request_line,
230*6777b538SAndroid Build Coastguard Worker     NetLogCaptureMode capture_mode) const {
231*6777b538SAndroid Build Coastguard Worker   base::Value::Dict dict;
232*6777b538SAndroid Build Coastguard Worker   dict.Set("line", NetLogStringValue(request_line));
233*6777b538SAndroid Build Coastguard Worker   base::Value::List headers;
234*6777b538SAndroid Build Coastguard Worker   for (const auto& header : headers_) {
235*6777b538SAndroid Build Coastguard Worker     std::string log_value =
236*6777b538SAndroid Build Coastguard Worker         ElideHeaderValueForNetLog(capture_mode, header.key, header.value);
237*6777b538SAndroid Build Coastguard Worker     headers.Append(
238*6777b538SAndroid Build Coastguard Worker         NetLogStringValue(base::StrCat({header.key, ": ", log_value})));
239*6777b538SAndroid Build Coastguard Worker   }
240*6777b538SAndroid Build Coastguard Worker   dict.Set("headers", std::move(headers));
241*6777b538SAndroid Build Coastguard Worker   return dict;
242*6777b538SAndroid Build Coastguard Worker }
243*6777b538SAndroid Build Coastguard Worker 
SetAcceptEncodingIfMissing(const GURL & url,const std::optional<base::flat_set<SourceStream::SourceType>> & accepted_stream_types,bool enable_brotli,bool enable_zstd)244*6777b538SAndroid Build Coastguard Worker void HttpRequestHeaders::SetAcceptEncodingIfMissing(
245*6777b538SAndroid Build Coastguard Worker     const GURL& url,
246*6777b538SAndroid Build Coastguard Worker     const std::optional<base::flat_set<SourceStream::SourceType>>&
247*6777b538SAndroid Build Coastguard Worker         accepted_stream_types,
248*6777b538SAndroid Build Coastguard Worker     bool enable_brotli,
249*6777b538SAndroid Build Coastguard Worker     bool enable_zstd) {
250*6777b538SAndroid Build Coastguard Worker   if (HasHeader(kAcceptEncoding))
251*6777b538SAndroid Build Coastguard Worker     return;
252*6777b538SAndroid Build Coastguard Worker 
253*6777b538SAndroid Build Coastguard Worker   // If a range is specifically requested, set the "Accepted Encoding" header to
254*6777b538SAndroid Build Coastguard Worker   // "identity".
255*6777b538SAndroid Build Coastguard Worker   if (HasHeader(kRange)) {
256*6777b538SAndroid Build Coastguard Worker     SetHeader(kAcceptEncoding, "identity");
257*6777b538SAndroid Build Coastguard Worker     return;
258*6777b538SAndroid Build Coastguard Worker   }
259*6777b538SAndroid Build Coastguard Worker 
260*6777b538SAndroid Build Coastguard Worker   // Supply Accept-Encoding headers first so that it is more likely that they
261*6777b538SAndroid Build Coastguard Worker   // will be in the first transmitted packet. This can sometimes make it easier
262*6777b538SAndroid Build Coastguard Worker   // to filter and analyze the streams to assure that a proxy has not damaged
263*6777b538SAndroid Build Coastguard Worker   // these headers. Some proxies deliberately corrupt Accept-Encoding headers.
264*6777b538SAndroid Build Coastguard Worker   std::vector<std::string> advertised_encoding_names;
265*6777b538SAndroid Build Coastguard Worker   if (SupportsStreamType(accepted_stream_types,
266*6777b538SAndroid Build Coastguard Worker                          SourceStream::SourceType::TYPE_GZIP)) {
267*6777b538SAndroid Build Coastguard Worker     advertised_encoding_names.push_back("gzip");
268*6777b538SAndroid Build Coastguard Worker   }
269*6777b538SAndroid Build Coastguard Worker   if (SupportsStreamType(accepted_stream_types,
270*6777b538SAndroid Build Coastguard Worker                          SourceStream::SourceType::TYPE_DEFLATE)) {
271*6777b538SAndroid Build Coastguard Worker     advertised_encoding_names.push_back("deflate");
272*6777b538SAndroid Build Coastguard Worker   }
273*6777b538SAndroid Build Coastguard Worker 
274*6777b538SAndroid Build Coastguard Worker   const bool can_use_advanced_encodings =
275*6777b538SAndroid Build Coastguard Worker       (url.SchemeIsCryptographic() || IsLocalhost(url));
276*6777b538SAndroid Build Coastguard Worker 
277*6777b538SAndroid Build Coastguard Worker   // Advertise "br" encoding only if transferred data is opaque to proxy.
278*6777b538SAndroid Build Coastguard Worker   if (enable_brotli &&
279*6777b538SAndroid Build Coastguard Worker       SupportsStreamType(accepted_stream_types,
280*6777b538SAndroid Build Coastguard Worker                          SourceStream::SourceType::TYPE_BROTLI) &&
281*6777b538SAndroid Build Coastguard Worker       can_use_advanced_encodings) {
282*6777b538SAndroid Build Coastguard Worker     advertised_encoding_names.push_back("br");
283*6777b538SAndroid Build Coastguard Worker   }
284*6777b538SAndroid Build Coastguard Worker   // Advertise "zstd" encoding only if transferred data is opaque to proxy.
285*6777b538SAndroid Build Coastguard Worker   if (enable_zstd &&
286*6777b538SAndroid Build Coastguard Worker       SupportsStreamType(accepted_stream_types,
287*6777b538SAndroid Build Coastguard Worker                          SourceStream::SourceType::TYPE_ZSTD) &&
288*6777b538SAndroid Build Coastguard Worker       can_use_advanced_encodings) {
289*6777b538SAndroid Build Coastguard Worker     advertised_encoding_names.push_back("zstd");
290*6777b538SAndroid Build Coastguard Worker   }
291*6777b538SAndroid Build Coastguard Worker   if (!advertised_encoding_names.empty()) {
292*6777b538SAndroid Build Coastguard Worker     // Tell the server what compression formats are supported.
293*6777b538SAndroid Build Coastguard Worker     SetHeader(
294*6777b538SAndroid Build Coastguard Worker         kAcceptEncoding,
295*6777b538SAndroid Build Coastguard Worker         base::JoinString(base::make_span(advertised_encoding_names), ", "));
296*6777b538SAndroid Build Coastguard Worker   }
297*6777b538SAndroid Build Coastguard Worker }
298*6777b538SAndroid Build Coastguard Worker 
FindHeader(std::string_view key)299*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders::HeaderVector::iterator HttpRequestHeaders::FindHeader(
300*6777b538SAndroid Build Coastguard Worker     std::string_view key) {
301*6777b538SAndroid Build Coastguard Worker   for (auto it = headers_.begin(); it != headers_.end(); ++it) {
302*6777b538SAndroid Build Coastguard Worker     if (base::EqualsCaseInsensitiveASCII(key, it->key))
303*6777b538SAndroid Build Coastguard Worker       return it;
304*6777b538SAndroid Build Coastguard Worker   }
305*6777b538SAndroid Build Coastguard Worker 
306*6777b538SAndroid Build Coastguard Worker   return headers_.end();
307*6777b538SAndroid Build Coastguard Worker }
308*6777b538SAndroid Build Coastguard Worker 
FindHeader(std::string_view key) const309*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders::HeaderVector::const_iterator HttpRequestHeaders::FindHeader(
310*6777b538SAndroid Build Coastguard Worker     std::string_view key) const {
311*6777b538SAndroid Build Coastguard Worker   for (auto it = headers_.begin(); it != headers_.end(); ++it) {
312*6777b538SAndroid Build Coastguard Worker     if (base::EqualsCaseInsensitiveASCII(key, it->key))
313*6777b538SAndroid Build Coastguard Worker       return it;
314*6777b538SAndroid Build Coastguard Worker   }
315*6777b538SAndroid Build Coastguard Worker 
316*6777b538SAndroid Build Coastguard Worker   return headers_.end();
317*6777b538SAndroid Build Coastguard Worker }
318*6777b538SAndroid Build Coastguard Worker 
SetHeaderInternal(std::string_view key,std::string && value)319*6777b538SAndroid Build Coastguard Worker void HttpRequestHeaders::SetHeaderInternal(std::string_view key,
320*6777b538SAndroid Build Coastguard Worker                                            std::string&& value) {
321*6777b538SAndroid Build Coastguard Worker   auto it = FindHeader(key);
322*6777b538SAndroid Build Coastguard Worker   if (it != headers_.end())
323*6777b538SAndroid Build Coastguard Worker     it->value = std::move(value);
324*6777b538SAndroid Build Coastguard Worker   else
325*6777b538SAndroid Build Coastguard Worker     headers_.emplace_back(key, std::move(value));
326*6777b538SAndroid Build Coastguard Worker }
327*6777b538SAndroid Build Coastguard Worker 
328*6777b538SAndroid Build Coastguard Worker }  // namespace net
329