• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // HttpRequestHeaders manages the request headers.
6 // It maintains these in a vector of header key/value pairs, thereby maintaining
7 // the order of the headers.  This means that any lookups are linear time
8 // operations.
9 
10 #ifndef NET_HTTP_HTTP_REQUEST_HEADERS_H_
11 #define NET_HTTP_HTTP_REQUEST_HEADERS_H_
12 
13 #include <memory>
14 #include <string>
15 #include <vector>
16 
17 #include "base/containers/flat_set.h"
18 #include "base/strings/string_piece.h"
19 #include "base/values.h"
20 #include "net/base/net_export.h"
21 #include "net/filter/source_stream.h"
22 #include "net/log/net_log_capture_mode.h"
23 #include "third_party/abseil-cpp/absl/types/optional.h"
24 #include "url/gurl.h"
25 
26 namespace net {
27 
28 class NET_EXPORT HttpRequestHeaders {
29  public:
30   struct NET_EXPORT HeaderKeyValuePair {
31     HeaderKeyValuePair();
32     HeaderKeyValuePair(base::StringPiece key, base::StringPiece value);
33     HeaderKeyValuePair(base::StringPiece key, std::string&& value);
34     // Inline to take advantage of the base::StringPiece constructor being
35     // constexpr.
HeaderKeyValuePairHeaderKeyValuePair36     HeaderKeyValuePair(base::StringPiece key, const char* value)
37         : HeaderKeyValuePair(key, base::StringPiece(value)) {}
38 
39     std::string key;
40     std::string value;
41   };
42 
43   typedef std::vector<HeaderKeyValuePair> HeaderVector;
44 
45   class NET_EXPORT Iterator {
46    public:
47     explicit Iterator(const HttpRequestHeaders& headers);
48 
49     Iterator(const Iterator&) = delete;
50     Iterator& operator=(const Iterator&) = delete;
51 
52     ~Iterator();
53 
54     // Advances the iterator to the next header, if any.  Returns true if there
55     // is a next header.  Use name() and value() methods to access the resultant
56     // header name and value.
57     bool GetNext();
58 
59     // These two accessors are only valid if GetNext() returned true.
name()60     const std::string& name() const { return curr_->key; }
value()61     const std::string& value() const { return curr_->value; }
62 
63    private:
64     bool started_ = false;
65     HttpRequestHeaders::HeaderVector::const_iterator curr_;
66     const HttpRequestHeaders::HeaderVector::const_iterator end_;
67   };
68 
69   static const char kConnectMethod[];
70   static const char kDeleteMethod[];
71   static const char kGetMethod[];
72   static const char kHeadMethod[];
73   static const char kOptionsMethod[];
74   static const char kPatchMethod[];
75   static const char kPostMethod[];
76   static const char kPutMethod[];
77   static const char kTraceMethod[];
78   static const char kTrackMethod[];
79 
80   static const char kAccept[];
81   static const char kAcceptCharset[];
82   static const char kAcceptEncoding[];
83   static const char kAcceptLanguage[];
84   static const char kAuthorization[];
85   static const char kCacheControl[];
86   static const char kConnection[];
87   static const char kContentType[];
88   static const char kCookie[];
89   static const char kContentLength[];
90   static const char kHost[];
91   static const char kIfMatch[];
92   static const char kIfModifiedSince[];
93   static const char kIfNoneMatch[];
94   static const char kIfRange[];
95   static const char kIfUnmodifiedSince[];
96   static const char kOrigin[];
97   static const char kPragma[];
98   static const char kProxyAuthorization[];
99   static const char kProxyConnection[];
100   static const char kRange[];
101   static const char kReferer[];
102   static const char kTransferEncoding[];
103   static const char kUserAgent[];
104 
105   HttpRequestHeaders();
106   HttpRequestHeaders(const HttpRequestHeaders& other);
107   HttpRequestHeaders(HttpRequestHeaders&& other);
108   ~HttpRequestHeaders();
109 
110   HttpRequestHeaders& operator=(const HttpRequestHeaders& other);
111   HttpRequestHeaders& operator=(HttpRequestHeaders&& other);
112 
IsEmpty()113   bool IsEmpty() const { return headers_.empty(); }
114 
HasHeader(base::StringPiece key)115   bool HasHeader(base::StringPiece key) const {
116     return FindHeader(key) != headers_.end();
117   }
118 
119   // Gets the first header that matches |key|.  If found, returns true and
120   // writes the value to |out|.
121   bool GetHeader(base::StringPiece key, std::string* out) const;
122 
123   // Clears all the headers.
124   void Clear();
125 
126   // Sets the header value pair for |key| and |value|.  If |key| already exists,
127   // then the header value is modified, but the key is untouched, and the order
128   // in the vector remains the same.  When comparing |key|, case is ignored.
129   // The caller must ensure that |key| passes HttpUtil::IsValidHeaderName() and
130   // |value| passes HttpUtil::IsValidHeaderValue().
131   void SetHeader(base::StringPiece key, base::StringPiece value);
132   void SetHeader(base::StringPiece key, std::string&& value);
133   // Inline to take advantage of the base::StringPiece constructor being
134   // constexpr.
SetHeader(base::StringPiece key,const char * value)135   void SetHeader(base::StringPiece key, const char* value) {
136     SetHeader(key, base::StringPiece(value));
137   }
138 
139   // Does the same as above but without internal DCHECKs for validations.
140   void SetHeaderWithoutCheckForTesting(base::StringPiece key,
141                                        base::StringPiece value);
142 
143   // Sets the header value pair for |key| and |value|, if |key| does not exist.
144   // If |key| already exists, the call is a no-op.
145   // When comparing |key|, case is ignored.
146   //
147   // The caller must ensure that |key| passes HttpUtil::IsValidHeaderName() and
148   // |value| passes HttpUtil::IsValidHeaderValue().
149   void SetHeaderIfMissing(base::StringPiece key, base::StringPiece value);
150 
151   // Removes the first header that matches (case insensitive) |key|.
152   void RemoveHeader(base::StringPiece key);
153 
154   // Parses the header from a string and calls SetHeader() with it.  This string
155   // should not contain any CRLF.  As per RFC7230 Section 3.2, the format is:
156   //
157   // header-field   = field-name ":" OWS field-value OWS
158   //
159   // field-name     = token
160   // field-value    = *( field-content / obs-fold )
161   // field-content  = field-vchar [ 1*( SP / HTAB ) field-vchar ]
162   // field-vchar    = VCHAR / obs-text
163   //
164   // obs-fold       = CRLF 1*( SP / HTAB )
165   //                ; obsolete line folding
166   //                ; see Section 3.2.4
167   //
168   // AddHeaderFromString() will trim any LWS surrounding the
169   // field-content.
170   void AddHeaderFromString(base::StringPiece header_line);
171 
172   // Same thing as AddHeaderFromString() except that |headers| is a "\r\n"
173   // delimited string of header lines.  It will split up the string by "\r\n"
174   // and call AddHeaderFromString() on each.
175   void AddHeadersFromString(base::StringPiece headers);
176 
177   // Calls SetHeader() on each header from |other|, maintaining order.
178   void MergeFrom(const HttpRequestHeaders& other);
179 
180   // Copies from |other| to |this|.
CopyFrom(const HttpRequestHeaders & other)181   void CopyFrom(const HttpRequestHeaders& other) { *this = other; }
182 
Swap(HttpRequestHeaders * other)183   void Swap(HttpRequestHeaders* other) { headers_.swap(other->headers_); }
184 
185   // Serializes HttpRequestHeaders to a string representation.  Joins all the
186   // header keys and values with ": ", and inserts "\r\n" between each header
187   // line, and adds the trailing "\r\n".
188   std::string ToString() const;
189 
190   // Takes in the request line and returns a Value for use with the NetLog
191   // containing both the request line and all headers fields.
192   base::Value::Dict NetLogParams(const std::string& request_line,
193                                  NetLogCaptureMode capture_mode) const;
194 
GetHeaderVector()195   const HeaderVector& GetHeaderVector() const { return headers_; }
196 
197   // Sets Accept-Encoding header based on `url` and `accepted_stream_types`, if
198   // it does not exist. "br" is appended only when `enable_brotli` is true.
199   void SetAcceptEncodingIfMissing(
200       const GURL& url,
201       const absl::optional<base::flat_set<SourceStream::SourceType>>&
202           accepted_stream_types,
203       bool enable_brotli);
204 
205  private:
206   HeaderVector::iterator FindHeader(base::StringPiece key);
207   HeaderVector::const_iterator FindHeader(base::StringPiece key) const;
208 
209   void SetHeaderInternal(base::StringPiece key, std::string&& value);
210 
211   HeaderVector headers_;
212 
213   // Allow the copy construction and operator= to facilitate copying in
214   // HttpRequestHeaders.
215   // TODO(willchan): Investigate to see if we can remove the need to copy
216   // HttpRequestHeaders.
217   // DISALLOW_COPY_AND_ASSIGN(HttpRequestHeaders);
218 };
219 
220 }  // namespace net
221 
222 #endif  // NET_HTTP_HTTP_REQUEST_HEADERS_H_
223