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