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