xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/balsa/header_api.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2022 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 #ifndef QUICHE_BALSA_HEADER_API_H_
6 #define QUICHE_BALSA_HEADER_API_H_
7 
8 #include <cstddef>
9 #include <functional>
10 #include <string>
11 #include <vector>
12 
13 #include "absl/strings/string_view.h"
14 #include "quiche/common/platform/api/quiche_export.h"
15 #include "quiche/common/platform/api/quiche_lower_case_string.h"
16 #include "quiche/common/quiche_callbacks.h"
17 
18 namespace quiche {
19 
20 // An API so we can reuse functions for BalsaHeaders and Envoy's HeaderMap.
21 // Contains only const member functions, so it can wrap const HeaderMaps;
22 // non-const functions are in HeaderApi.
23 //
24 // Depending on the implementation, the headers may act like HTTP/1 headers
25 // (BalsaHeaders) or HTTP/2 headers (HeaderMap). For HTTP-version-specific
26 // headers or pseudoheaders like "host" or ":authority", use this API's
27 // implementation-independent member functions, like Authority(). Looking those
28 // headers up by name is deprecated and may QUICHE_DCHECK-fail.
29 // For the differences between HTTP/1 and HTTP/2 headers, see RFC 7540:
30 // https://tools.ietf.org/html/rfc7540#section-8.1.2
31 //
32 // Operations on header keys are case-insensitive while operations on header
33 // values are case-sensitive.
34 //
35 // Some methods have overloads which accept Envoy-style LowerCaseStrings. Often
36 // these keys are accessible from Envoy::Http::Headers::get().SomeHeader,
37 // already lowercaseified. It's faster to avoid converting them to and from
38 // lowercase. Additionally, some implementations of ConstHeaderApi might take
39 // advantage of a constant-time lookup for inlined headers.
40 class QUICHE_EXPORT ConstHeaderApi {
41  public:
~ConstHeaderApi()42   virtual ~ConstHeaderApi() {}
43 
44   // Determine whether the headers are empty.
45   virtual bool IsEmpty() const = 0;
46 
47   // Returns the header entry for the first instance with key |key|
48   // If header isn't present, returns absl::string_view().
49   virtual absl::string_view GetHeader(absl::string_view key) const = 0;
50 
GetHeader(const QuicheLowerCaseString & key)51   virtual absl::string_view GetHeader(const QuicheLowerCaseString& key) const {
52     // Default impl for BalsaHeaders, etc.
53     return GetHeader(key.get());
54   }
55 
56   // Collects all of the header entries with key |key| and returns them in |out|
57   // Headers are returned in the order they are inserted.
58   virtual void GetAllOfHeader(absl::string_view key,
59                               std::vector<absl::string_view>* out) const = 0;
GetAllOfHeader(absl::string_view key)60   virtual std::vector<absl::string_view> GetAllOfHeader(
61       absl::string_view key) const {
62     std::vector<absl::string_view> out;
63     GetAllOfHeader(key, &out);
64     return out;
65   }
GetAllOfHeader(const QuicheLowerCaseString & key,std::vector<absl::string_view> * out)66   virtual void GetAllOfHeader(const QuicheLowerCaseString& key,
67                               std::vector<absl::string_view>* out) const {
68     return GetAllOfHeader(key.get(), out);
69   }
70 
71   // Determine if a given header is present.
72   virtual bool HasHeader(absl::string_view key) const = 0;
73 
74   // Determines if a given header is present with non-empty value.
75   virtual bool HasNonEmptyHeader(absl::string_view key) const = 0;
76 
77   // Goes through all headers with key |key| and checks to see if one of the
78   // values is |value|.  Returns true if there are headers with the desired key
79   // and value, false otherwise.
80   virtual bool HeaderHasValue(absl::string_view key,
81                               absl::string_view value) const = 0;
82 
83   // Same as above, but value is treated as case insensitive.
84   virtual bool HeaderHasValueIgnoreCase(absl::string_view key,
85                                         absl::string_view value) const = 0;
86 
87   // Joins all values for header entries with `key` into a comma-separated
88   // string.  Headers are returned in the order they are inserted.
89   virtual std::string GetAllOfHeaderAsString(absl::string_view key) const = 0;
GetAllOfHeaderAsString(const QuicheLowerCaseString & key)90   virtual std::string GetAllOfHeaderAsString(
91       const QuicheLowerCaseString& key) const {
92     return GetAllOfHeaderAsString(key.get());
93   }
94 
95   // Returns true if we have at least one header with given prefix
96   // [case insensitive]. Currently for test use only.
97   virtual bool HasHeadersWithPrefix(absl::string_view key) const = 0;
98 
99   // Returns the key value pairs for all headers where the header key begins
100   // with the specified prefix.
101   // Headers are returned in the order they are inserted.
102   virtual void GetAllOfHeaderWithPrefix(
103       absl::string_view prefix,
104       std::vector<std::pair<absl::string_view, absl::string_view>>* out)
105       const = 0;
106 
107   // Returns the key value pairs for all headers in this object. If 'limit' is
108   // >= 0, return at most 'limit' headers.
109   virtual void GetAllHeadersWithLimit(
110       std::vector<std::pair<absl::string_view, absl::string_view>>* out,
111       int limit) const = 0;
112 
113   // Returns a textual representation of the header object. The format of the
114   // string may depend on the underlying implementation.
115   virtual std::string DebugString() const = 0;
116 
117   // Applies the argument function to each header line.  If the argument
118   // function returns false, iteration stops and ForEachHeader returns false;
119   // otherwise, ForEachHeader returns true.
120   virtual bool ForEachHeader(
121       quiche::UnretainedCallback<bool(const absl::string_view key,
122                                       const absl::string_view value)>
123           fn) const = 0;
124 
125   // Returns the upper bound byte size of the headers. This can be used to size
126   // a Buffer when serializing headers.
127   virtual size_t GetSizeForWriteBuffer() const = 0;
128 
129   // Returns the response code for response headers. If no status code exists,
130   // the return value is implementation-specific.
131   virtual absl::string_view response_code() const = 0;
132 
133   // Returns the response code for response headers or 0 if no status code
134   // exists.
135   virtual size_t parsed_response_code() const = 0;
136 
137   // Returns the response reason phrase; the stored one for HTTP/1 headers, or a
138   // phrase determined from the response code for HTTP/2 headers..
139   virtual absl::string_view response_reason_phrase() const = 0;
140 
141   // Return the HTTP first line of this request, generally of the format:
142   // GET /path/ HTTP/1.1
143   // TODO(b/110421449): deprecate this method.
144   virtual std::string first_line_of_request() const = 0;
145 
146   // Return the method for this request, such as GET or POST.
147   virtual absl::string_view request_method() const = 0;
148 
149   // Return the request URI from the first line of this request, such as
150   // "/path/".
151   virtual absl::string_view request_uri() const = 0;
152 
153   // Return the version portion of the first line of this request, such as
154   // "HTTP/1.1".
155   // TODO(b/110421449): deprecate this method.
156   virtual absl::string_view request_version() const = 0;
157 
158   virtual absl::string_view response_version() const = 0;
159 
160   // Returns the authority portion of a request, or an empty string if missing.
161   // This is the value of the host header for HTTP/1 headers and the value of
162   // the :authority pseudo-header for HTTP/2 headers.
163   virtual absl::string_view Authority() const = 0;
164 
165   // Call the provided function on the cookie, avoiding
166   // copies if possible. The cookie is the value of the Cookie header; for
167   // HTTP/2 headers, if there are multiple Cookie headers, they will be joined
168   // by "; ", per go/rfc/7540#section-8.1.2.5. If there is no Cookie header,
169   // cookie.data() will be nullptr. The lifetime of the cookie isn't guaranteed
170   // to extend beyond this call.
171   virtual void ApplyToCookie(
172       quiche::UnretainedCallback<void(absl::string_view cookie)> f) const = 0;
173 
174   virtual size_t content_length() const = 0;
175   virtual bool content_length_valid() const = 0;
176 
177   // TODO(b/118501626): Add functions for working with other headers and
178   // pseudo-headers whose presence or value depends on HTTP version, including:
179   // :method, :scheme, :path, connection, and cookie.
180 };
181 
182 // An API so we can reuse functions for BalsaHeaders and Envoy's HeaderMap.
183 // Inherits const functions from ConstHeaderApi and adds non-const functions,
184 // for use with non-const HeaderMaps.
185 //
186 // For HTTP-version-specific headers and pseudo-headers, the same caveats apply
187 // as with ConstHeaderApi.
188 //
189 // Operations on header keys are case-insensitive while operations on header
190 // values are case-sensitive.
191 class QUICHE_EXPORT HeaderApi : public virtual ConstHeaderApi {
192  public:
193   // Replaces header entries with key |key| if they exist, or appends
194   // a new header if none exist.
195   virtual void ReplaceOrAppendHeader(absl::string_view key,
196                                      absl::string_view value) = 0;
197 
198   // Removes all headers in given set of |keys| at once
199   virtual void RemoveAllOfHeaderInList(
200       const std::vector<absl::string_view>& keys) = 0;
201 
202   // Removes all headers with key |key|.
203   virtual void RemoveAllOfHeader(absl::string_view key) = 0;
204 
205   // Append a new header entry to the header object with key |key| and value
206   // |value|.
207   virtual void AppendHeader(absl::string_view key, absl::string_view value) = 0;
208 
209   // Removes all headers starting with 'key' [case insensitive]
210   virtual void RemoveAllHeadersWithPrefix(absl::string_view key) = 0;
211 
212   // Appends ',value' to an existing header named 'key'.  If no header with the
213   // correct key exists, it will call AppendHeader(key, value).  Calling this
214   // function on a key which exists several times in the headers will produce
215   // unpredictable results.
216   virtual void AppendToHeader(absl::string_view key,
217                               absl::string_view value) = 0;
218 
219   // Appends ', value' to an existing header named 'key'.  If no header with the
220   // correct key exists, it will call AppendHeader(key, value).  Calling this
221   // function on a key which exists several times in the headers will produce
222   // unpredictable results.
223   virtual void AppendToHeaderWithCommaAndSpace(absl::string_view key,
224                                                absl::string_view value) = 0;
225 
226   // Set the header or pseudo-header corresponding to the authority portion of a
227   // request: host for HTTP/1 headers, or :authority for HTTP/2 headers.
228   virtual void ReplaceOrAppendAuthority(absl::string_view value) = 0;
229   virtual void RemoveAuthority() = 0;
230 
231   // These set portions of the first line for HTTP/1 headers, or the
232   // corresponding pseudo-headers for HTTP/2 headers.
233   virtual void SetRequestMethod(absl::string_view method) = 0;
234   virtual void SetResponseCode(absl::string_view code) = 0;
235   // As SetResponseCode, but slightly faster for BalsaHeaders if the caller
236   // represents the response code as an integer and not a string.
237   virtual void SetParsedResponseCodeAndUpdateFirstline(
238       size_t parsed_response_code) = 0;
239 
240   // Sets the request URI.
241   //
242   // For HTTP/1 headers, sets the request URI portion of the first line (the
243   // second token). Doesn't parse the URI; leaves the Host header unchanged.
244   //
245   // For HTTP/2 headers, sets the :path pseudo-header, and also :scheme and
246   // :authority if they're present in the URI; otherwise, leaves :scheme and
247   // :authority unchanged.
248   //
249   // The caller is responsible for verifying that the URI is in a valid format.
250   virtual void SetRequestUri(absl::string_view uri) = 0;
251 
252   // These are only meaningful for HTTP/1 headers; for HTTP/2 headers, they do
253   // nothing.
254   virtual void SetRequestVersion(absl::string_view version) = 0;
255   virtual void SetResponseVersion(absl::string_view version) = 0;
256   virtual void SetResponseReasonPhrase(absl::string_view reason_phrase) = 0;
257 
258   // SetContentLength, SetTransferEncodingToChunkedAndClearContentLength, and
259   // SetNoTransferEncoding modifies the header object to use
260   // content-length and transfer-encoding headers in a consistent
261   // manner. They set all internal flags and status, if applicable, so client
262   // can get a consistent view from various accessors.
263   virtual void SetContentLength(size_t length) = 0;
264   // Sets transfer-encoding to chunked and updates internal state.
265   virtual void SetTransferEncodingToChunkedAndClearContentLength() = 0;
266   // Removes transfer-encoding headers and updates internal state.
267   virtual void SetNoTransferEncoding() = 0;
268 
269   // If true, QUICHE_BUG if a header that starts with an invalid prefix is
270   // explicitly set. Not implemented for Envoy headers; can only be set false.
271   virtual void set_enforce_header_policy(bool enforce) = 0;
272 };
273 
274 }  // namespace quiche
275 
276 #endif  // QUICHE_BALSA_HEADER_API_H_
277