LCOV - code coverage report
Current view: top level - envoy/http - header_map.h (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 146 174 83.9 %
Date: 2024-01-05 06:35:25 Functions: 53 754 7.0 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include <algorithm>
       4             : #include <cstdint>
       5             : #include <cstring>
       6             : #include <iostream>
       7             : #include <memory>
       8             : #include <string>
       9             : #include <type_traits>
      10             : #include <vector>
      11             : 
      12             : #include "envoy/common/optref.h"
      13             : #include "envoy/common/pure.h"
      14             : #include "envoy/common/union_string.h"
      15             : #include "envoy/http/header_formatter.h"
      16             : 
      17             : #include "source/common/common/assert.h"
      18             : #include "source/common/common/hash.h"
      19             : #include "source/common/common/macros.h"
      20             : 
      21             : #include "absl/container/inlined_vector.h"
      22             : #include "absl/strings/string_view.h"
      23             : 
      24             : namespace Envoy {
      25             : namespace Http {
      26             : 
      27             : // Used by ASSERTs to validate internal consistency. E.g. valid HTTP header keys/values should
      28             : // never contain embedded NULLs.
      29        3274 : static inline bool validHeaderString(absl::string_view s) {
      30           0 :   // If you modify this list of illegal embedded characters you will probably
      31           0 :   // want to change header_map_fuzz_impl_test at the same time.
      32       19767 :   for (const char c : s) {
      33       19767 :     switch (c) {
      34           0 :     case '\0':
      35           0 :       FALLTHRU;
      36           4 :     case '\r':
      37           4 :       FALLTHRU;
      38           4 :     case '\n':
      39           4 :       return false;
      40       19763 :     default:
      41       19763 :       continue;
      42       19767 :     }
      43       19767 :   }
      44        3270 :   return true;
      45        3274 : }
      46             : 
      47             : /**
      48             :  * Wrapper for a lower case string used in header operations to generally avoid needless case
      49             :  * insensitive compares.
      50             :  */
      51             : class LowerCaseString {
      52             : public:
      53         731 :   LowerCaseString(LowerCaseString&& rhs) noexcept : string_(std::move(rhs.string_)) {
      54         731 :     ASSERT(valid());
      55         731 :   }
      56           0 :   LowerCaseString& operator=(LowerCaseString&& rhs) noexcept {
      57           0 :     string_ = std::move(rhs.string_);
      58           0 :     ASSERT(valid());
      59           0 :     return *this;
      60           0 :   }
      61             : 
      62        2983 :   LowerCaseString(const LowerCaseString& rhs) : string_(rhs.string_) { ASSERT(valid()); }
      63           0 :   LowerCaseString& operator=(const LowerCaseString& rhs) {
      64           0 :     string_ = std::move(rhs.string_);
      65           0 :     ASSERT(valid());
      66           0 :     return *this;
      67           0 :   }
      68             : 
      69       81929 :   explicit LowerCaseString(absl::string_view new_string) : string_(new_string) {
      70       81929 :     ASSERT(valid());
      71       81929 :     lower();
      72       81929 :   }
      73             : 
      74      188957 :   const std::string& get() const { return string_; }
      75        1385 :   bool operator==(const LowerCaseString& rhs) const { return string_ == rhs.string_; }
      76          18 :   bool operator!=(const LowerCaseString& rhs) const { return string_ != rhs.string_; }
      77       56157 :   bool operator<(const LowerCaseString& rhs) const { return string_.compare(rhs.string_) < 0; }
      78             : 
      79           0 :   friend std::ostream& operator<<(std::ostream& os, const LowerCaseString& lower_case_string) {
      80           0 :     return os << lower_case_string.string_;
      81           0 :   }
      82             : 
      83             :   // Implicit conversion to absl::string_view.
      84       12358 :   operator absl::string_view() const { return string_; }
      85             : 
      86             : private:
      87       81929 :   void lower() {
      88       81929 :     std::transform(string_.begin(), string_.end(), string_.begin(), absl::ascii_tolower);
      89       81929 :   }
      90           0 :   bool valid() const { return validHeaderString(string_); }
      91             : 
      92             :   std::string string_;
      93             : };
      94             : 
      95             : /**
      96             :  * Convenient type for a vector of lower case string and string pair.
      97             :  */
      98             : using LowerCaseStrPairVector =
      99             :     std::vector<std::pair<const Http::LowerCaseString, const std::string>>;
     100             : 
     101             : class HeaderStringValidator {
     102             : public:
     103           0 :   bool operator()(absl::string_view view) {
     104           0 :     return disable_validation_for_tests_ ? true : validHeaderString(view);
     105           0 :   }
     106             : 
     107             :   // This flag allows disabling the check for the NUL, CR and LF characters in the
     108             :   // header names or values in the DEBUG builds to prevent the `ASSERT(valid())` in the
     109             :   // HeaderString constructor from failing tests.
     110             :   static bool disable_validation_for_tests_;
     111             : };
     112             : 
     113             : class HeaderString : public UnionStringBase<HeaderStringValidator> {
     114             : public:
     115             :   using UnionStringBase::UnionStringBase;
     116             : 
     117             :   /**
     118             :    * Constructor for a lower case string reference.
     119             :    * @param ref_value MUST point to data that will live beyond the lifetime of any request/response
     120             :    *        using the string (since a codec may optimize for zero copy).
     121             :    */
     122             :   explicit HeaderString(const LowerCaseString& ref_value) noexcept;
     123             : 
     124             :   /**
     125             :    * Constructor for normal UnionString instance.
     126             :    * @param move_value moveable UnionString. The string value MUST be valid header string.
     127             :    */
     128             :   explicit HeaderString(UnionString&& move_value) noexcept;
     129             : };
     130             : 
     131             : /**
     132             :  * Encapsulates an individual header entry (including both key and value).
     133             :  */
     134             : class HeaderEntry {
     135             : public:
     136       91201 :   virtual ~HeaderEntry() = default;
     137             : 
     138             :   /**
     139             :    * @return the header key.
     140             :    */
     141             :   virtual const HeaderString& key() const PURE;
     142             : 
     143             :   /**
     144             :    * Set the header value by copying data into it.
     145             :    */
     146             :   virtual void value(absl::string_view value) PURE;
     147             : 
     148             :   /**
     149             :    * Set the header value by copying an integer into it.
     150             :    */
     151             :   virtual void value(uint64_t value) PURE;
     152             : 
     153             :   /**
     154             :    * Set the header value by copying the value in another header entry.
     155             :    */
     156             :   virtual void value(const HeaderEntry& header) PURE;
     157             : 
     158             :   /**
     159             :    * @return the header value.
     160             :    */
     161             :   virtual const HeaderString& value() const PURE;
     162             : 
     163             :   /**
     164             :    * @return the header value.
     165             :    */
     166             :   virtual HeaderString& value() PURE;
     167             : 
     168             : private:
     169             :   void value(const char*); // Do not allow auto conversion to std::string
     170             : };
     171             : 
     172             : /**
     173             :  * The following defines all default request headers that Envoy allows direct access to inside of
     174             :  * the header map. In practice, these are all headers used during normal Envoy request flow
     175             :  * processing. This allows O(1) access to these headers without even a hash lookup.
     176             :  *
     177             :  */
     178             : #define INLINE_REQ_STRING_HEADERS(HEADER_FUNC)                                                     \
     179          33 :   HEADER_FUNC(ClientTraceId)                                                                       \
     180          33 :   HEADER_FUNC(EnvoyDownstreamServiceCluster)                                                       \
     181          33 :   HEADER_FUNC(EnvoyDownstreamServiceNode)                                                          \
     182          33 :   HEADER_FUNC(EnvoyExternalAddress)                                                                \
     183          33 :   HEADER_FUNC(EnvoyForceTrace)                                                                     \
     184          33 :   HEADER_FUNC(EnvoyHedgeOnPerTryTimeout)                                                           \
     185          33 :   HEADER_FUNC(EnvoyInternalRequest)                                                                \
     186          33 :   HEADER_FUNC(EnvoyIpTags)                                                                         \
     187          33 :   HEADER_FUNC(EnvoyRetryOn)                                                                        \
     188          33 :   HEADER_FUNC(EnvoyRetryGrpcOn)                                                                    \
     189          33 :   HEADER_FUNC(EnvoyRetriableStatusCodes)                                                           \
     190          33 :   HEADER_FUNC(EnvoyRetriableHeaderNames)                                                           \
     191          33 :   HEADER_FUNC(EnvoyIsTimeoutRetry)                                                                 \
     192          33 :   HEADER_FUNC(EnvoyOriginalPath)                                                                   \
     193          33 :   HEADER_FUNC(EnvoyOriginalUrl)                                                                    \
     194          33 :   HEADER_FUNC(EnvoyUpstreamAltStatName)                                                            \
     195          33 :   HEADER_FUNC(EnvoyUpstreamRequestTimeoutAltResponse)                                              \
     196          33 :   HEADER_FUNC(Expect)                                                                              \
     197          33 :   HEADER_FUNC(ForwardedClientCert)                                                                 \
     198          33 :   HEADER_FUNC(ForwardedFor)                                                                        \
     199          33 :   HEADER_FUNC(ForwardedHost)                                                                       \
     200          33 :   HEADER_FUNC(ForwardedProto)                                                                      \
     201          33 :   HEADER_FUNC(GrpcTimeout)                                                                         \
     202          33 :   HEADER_FUNC(Host)                                                                                \
     203          33 :   HEADER_FUNC(Method)                                                                              \
     204          33 :   HEADER_FUNC(Path)                                                                                \
     205          33 :   HEADER_FUNC(Protocol)                                                                            \
     206          33 :   HEADER_FUNC(Scheme)                                                                              \
     207          33 :   HEADER_FUNC(TE)                                                                                  \
     208          33 :   HEADER_FUNC(UserAgent)
     209             : 
     210             : #define INLINE_REQ_NUMERIC_HEADERS(HEADER_FUNC)                                                    \
     211          33 :   HEADER_FUNC(EnvoyExpectedRequestTimeoutMs)                                                       \
     212          33 :   HEADER_FUNC(EnvoyMaxRetries)                                                                     \
     213          33 :   HEADER_FUNC(EnvoyUpstreamRequestTimeoutMs)                                                       \
     214          33 :   HEADER_FUNC(EnvoyUpstreamRequestPerTryTimeoutMs)                                                 \
     215          33 :   HEADER_FUNC(EnvoyUpstreamStreamDurationMs)                                                       \
     216          33 :   HEADER_FUNC(ForwardedPort)
     217             : 
     218             : #define INLINE_REQ_HEADERS(HEADER_FUNC)                                                            \
     219          33 :   INLINE_REQ_STRING_HEADERS(HEADER_FUNC)                                                           \
     220          33 :   INLINE_REQ_NUMERIC_HEADERS(HEADER_FUNC)
     221             : 
     222             : /**
     223             :  * Default O(1) response headers.
     224             :  */
     225             : #define INLINE_RESP_STRING_HEADERS(HEADER_FUNC)                                                    \
     226          26 :   HEADER_FUNC(Date)                                                                                \
     227          26 :   HEADER_FUNC(EnvoyDegraded)                                                                       \
     228          26 :   HEADER_FUNC(EnvoyImmediateHealthCheckFail)                                                       \
     229          26 :   HEADER_FUNC(EnvoyRateLimited)                                                                    \
     230          26 :   HEADER_FUNC(EnvoyUpstreamCanary)                                                                 \
     231          26 :   HEADER_FUNC(EnvoyUpstreamHealthCheckedCluster)                                                   \
     232          26 :   HEADER_FUNC(Location)                                                                            \
     233          26 :   HEADER_FUNC(Server)
     234             : 
     235             : #define INLINE_RESP_NUMERIC_HEADERS(HEADER_FUNC)                                                   \
     236          26 :   HEADER_FUNC(EnvoyUpstreamServiceTime)                                                            \
     237          26 :   HEADER_FUNC(Status)
     238             : 
     239             : #define INLINE_RESP_HEADERS(HEADER_FUNC)                                                           \
     240          26 :   INLINE_RESP_STRING_HEADERS(HEADER_FUNC)                                                          \
     241          26 :   INLINE_RESP_NUMERIC_HEADERS(HEADER_FUNC)
     242             : 
     243             : /**
     244             :  * Default O(1) request and response headers.
     245             :  */
     246             : #define INLINE_REQ_RESP_STRING_HEADERS(HEADER_FUNC)                                                \
     247          59 :   HEADER_FUNC(Connection)                                                                          \
     248          59 :   HEADER_FUNC(ContentType)                                                                         \
     249          59 :   HEADER_FUNC(EnvoyDecoratorOperation)                                                             \
     250          59 :   HEADER_FUNC(KeepAlive)                                                                           \
     251          59 :   HEADER_FUNC(ProxyConnection)                                                                     \
     252          59 :   HEADER_FUNC(ProxyStatus)                                                                         \
     253          59 :   HEADER_FUNC(RequestId)                                                                           \
     254          59 :   HEADER_FUNC(TransferEncoding)                                                                    \
     255          59 :   HEADER_FUNC(Upgrade)                                                                             \
     256          59 :   HEADER_FUNC(Via)
     257             : 
     258             : #define INLINE_REQ_RESP_NUMERIC_HEADERS(HEADER_FUNC)                                               \
     259          59 :   HEADER_FUNC(ContentLength)                                                                       \
     260          59 :   HEADER_FUNC(EnvoyAttemptCount)
     261             : 
     262             : #define INLINE_REQ_RESP_HEADERS(HEADER_FUNC)                                                       \
     263          59 :   INLINE_REQ_RESP_STRING_HEADERS(HEADER_FUNC)                                                      \
     264          59 :   INLINE_REQ_RESP_NUMERIC_HEADERS(HEADER_FUNC)
     265             : 
     266             : /**
     267             :  * Default O(1) response headers and trailers.
     268             :  */
     269          49 : #define INLINE_RESP_STRING_HEADERS_TRAILERS(HEADER_FUNC) HEADER_FUNC(GrpcMessage)
     270             : 
     271          49 : #define INLINE_RESP_NUMERIC_HEADERS_TRAILERS(HEADER_FUNC) HEADER_FUNC(GrpcStatus)
     272             : 
     273             : #define INLINE_RESP_HEADERS_TRAILERS(HEADER_FUNC)                                                  \
     274          49 :   INLINE_RESP_STRING_HEADERS_TRAILERS(HEADER_FUNC)                                                 \
     275          49 :   INLINE_RESP_NUMERIC_HEADERS_TRAILERS(HEADER_FUNC)
     276             : 
     277             : /**
     278             :  * The following functions are defined for each inline header above.
     279             : 
     280             :  * E.g., for path we have:
     281             :  * Path() -> returns the header entry if it exists or nullptr.
     282             :  * removePath() -> removes the header if it exists.
     283             :  * setPath(path_string) -> sets the header value to the string path_string by copying the data.
     284             :  *
     285             :  */
     286             : #define DEFINE_INLINE_HEADER(name)                                                                 \
     287             :   virtual const HeaderEntry* name() const PURE;                                                    \
     288             :   virtual size_t remove##name() PURE;                                                              \
     289             :   virtual absl::string_view get##name##Value() const PURE;                                         \
     290             :   virtual void set##name(absl::string_view value) PURE;
     291             : 
     292             : /*
     293             :  * For inline headers that have string values, there are also:
     294             :  * appendPath(path, "/") -> appends the string path with delimiter "/" to the header value.
     295             :  * setReferencePath(PATH) -> sets header value to reference string PATH.
     296             :  *
     297             :  */
     298             : #define DEFINE_INLINE_STRING_HEADER(name)                                                          \
     299             :   DEFINE_INLINE_HEADER(name)                                                                       \
     300             :   virtual void append##name(absl::string_view data, absl::string_view delimiter) PURE;             \
     301             :   virtual void setReference##name(absl::string_view value) PURE;
     302             : 
     303             : /*
     304             :  * For inline headers that use integers, there is:
     305             :  * setContentLength(5) -> sets the header value to the integer 5.
     306             :  */
     307             : #define DEFINE_INLINE_NUMERIC_HEADER(name)                                                         \
     308             :   DEFINE_INLINE_HEADER(name)                                                                       \
     309             :   virtual void set##name(uint64_t) PURE;
     310             : 
     311             : /**
     312             :  * Wraps a set of HTTP headers.
     313             :  */
     314             : class HeaderMap {
     315             : public:
     316       14120 :   virtual ~HeaderMap() = default;
     317             : 
     318             :   /**
     319             :    * For testing. This is an exact match comparison (order matters).
     320             :    */
     321             :   virtual bool operator==(const HeaderMap& rhs) const PURE;
     322             :   virtual bool operator!=(const HeaderMap& rhs) const PURE;
     323             : 
     324             :   /**
     325             :    * Add a header via full move. This is the expected high performance paths for codecs populating
     326             :    * a map when receiving.
     327             :    * @param key supplies the header key.
     328             :    * @param value supplies the header value.
     329             :    */
     330             :   virtual void addViaMove(HeaderString&& key, HeaderString&& value) PURE;
     331             : 
     332             :   /**
     333             :    * Add a reference header to the map. Both key and value MUST point to data that will live beyond
     334             :    * the lifetime of any request/response using the string (since a codec may optimize for zero
     335             :    * copy). The key will not be copied and a best effort will be made not to
     336             :    * copy the value (but this may happen when comma concatenating, see below).
     337             :    *
     338             :    * Calling addReference multiple times for the same header will result in:
     339             :    * - Comma concatenation for predefined inline headers.
     340             :    * - Multiple headers being present in the HeaderMap for other headers.
     341             :    *
     342             :    * @param key specifies the name of the header to add; it WILL NOT be copied.
     343             :    * @param value specifies the value of the header to add; it WILL NOT be copied.
     344             :    */
     345             :   virtual void addReference(const LowerCaseString& key, absl::string_view value) PURE;
     346             : 
     347             :   /**
     348             :    * Add a header with a reference key to the map. The key MUST point to data that will live beyond
     349             :    * the lifetime of any request/response using the string (since a codec may optimize for zero
     350             :    * copy). The value will be copied.
     351             :    *
     352             :    * Calling addReference multiple times for the same header will result in:
     353             :    * - Comma concatenation for predefined inline headers.
     354             :    * - Multiple headers being present in the HeaderMap for other headers.
     355             :    *
     356             :    * @param key specifies the name of the header to add; it WILL NOT be copied.
     357             :    * @param value specifies the value of the header to add; it WILL be copied.
     358             :    */
     359             :   virtual void addReferenceKey(const LowerCaseString& key, uint64_t value) PURE;
     360             : 
     361             :   /**
     362             :    * Add a header with a reference key to the map. The key MUST point to data that will
     363             :    * live beyond the lifetime of any request/response using the string (since a codec may optimize
     364             :    * for zero copy). The value will be copied.
     365             :    *
     366             :    * Calling addReference multiple times for the same header will result in:
     367             :    * - Comma concatenation for predefined inline headers.
     368             :    * - Multiple headers being present in the HeaderMap for other headers.
     369             :    *
     370             :    * @param key specifies the name of the header to add; it WILL NOT be copied.
     371             :    * @param value specifies the value of the header to add; it WILL be copied.
     372             :    */
     373             :   virtual void addReferenceKey(const LowerCaseString& key, absl::string_view value) PURE;
     374             : 
     375             :   /**
     376             :    * Add a header by copying both the header key and the value.
     377             :    *
     378             :    * Calling addCopy multiple times for the same header will result in:
     379             :    * - Comma concatenation for predefined inline headers.
     380             :    * - Multiple headers being present in the HeaderMap for other headers.
     381             :    *
     382             :    * @param key specifies the name of the header to add; it WILL be copied.
     383             :    * @param value specifies the value of the header to add; it WILL be copied.
     384             :    */
     385             :   virtual void addCopy(const LowerCaseString& key, uint64_t value) PURE;
     386             : 
     387             :   /**
     388             :    * Add a header by copying both the header key and the value.
     389             :    *
     390             :    * Calling addCopy multiple times for the same header will result in:
     391             :    * - Comma concatenation for predefined inline headers.
     392             :    * - Multiple headers being present in the HeaderMap for other headers.
     393             :    *
     394             :    * @param key specifies the name of the header to add; it WILL be copied.
     395             :    * @param value specifies the value of the header to add; it WILL be copied.
     396             :    */
     397             :   virtual void addCopy(const LowerCaseString& key, absl::string_view value) PURE;
     398             : 
     399             :   /**
     400             :    * Appends data to header. If header already has a value, the string "," is added between the
     401             :    * existing value and data.
     402             :    *
     403             :    * @param key specifies the name of the header to append; it WILL be copied.
     404             :    * @param value specifies the value of the header to add; it WILL be copied.
     405             :    *
     406             :    * Caution: This iterates over the HeaderMap to find the header to append. This will modify only
     407             :    * the first occurrence of the header.
     408             :    * TODO(asraa): Investigate whether necessary to append to all headers with the key.
     409             :    */
     410             :   virtual void appendCopy(const LowerCaseString& key, absl::string_view value) PURE;
     411             : 
     412             :   /**
     413             :    * Set a reference header in the map. Both key and value MUST point to data that will live beyond
     414             :    * the lifetime of any request/response using the string (since a codec may optimize for zero
     415             :    * copy). Nothing will be copied.
     416             :    *
     417             :    * Calling setReference multiple times for the same header will result in only the last header
     418             :    * being present in the HeaderMap.
     419             :    *
     420             :    * @param key specifies the name of the header to set; it WILL NOT be copied.
     421             :    * @param value specifies the value of the header to set; it WILL NOT be copied.
     422             :    */
     423             :   virtual void setReference(const LowerCaseString& key, absl::string_view value) PURE;
     424             : 
     425             :   /**
     426             :    * Set a header with a reference key in the map. The key MUST point to point to data that will
     427             :    * live beyond the lifetime of any request/response using the string (since a codec may optimize
     428             :    * for zero copy). The value will be copied.
     429             :    *
     430             :    * Calling setReferenceKey multiple times for the same header will result in only the last header
     431             :    * being present in the HeaderMap.
     432             :    *
     433             :    * @param key specifies the name of the header to set; it WILL NOT be copied.
     434             :    * @param value specifies the value of the header to set; it WILL be copied.
     435             :    */
     436             :   virtual void setReferenceKey(const LowerCaseString& key, absl::string_view value) PURE;
     437             : 
     438             :   /**
     439             :    * Replaces a header value by copying the value. Copies the key if the key does not exist.
     440             :    * If there are multiple values for one header, this removes all existing values and add
     441             :    * the new one.
     442             :    *
     443             :    * Calling setCopy multiple times for the same header will result in only the last header
     444             :    * being present in the HeaderMap.
     445             :    *
     446             :    * @param key specifies the name of the header to set; it WILL be copied.
     447             :    * @param value specifies the value of the header to set; it WILL be copied.
     448             :    * TODO(asraa): Investigate whether necessary to set all headers with the key.
     449             :    */
     450             :   virtual void setCopy(const LowerCaseString& key, absl::string_view value) PURE;
     451             : 
     452             :   /**
     453             :    * @return uint64_t the size of the header map in bytes. This is the sum of the header keys and
     454             :    * values and does not account for data structure overhead.
     455             :    */
     456             :   virtual uint64_t byteSize() const PURE;
     457             : 
     458             :   /**
     459             :    * @return uint32_t the max size of the header map in kilobyte.
     460             :    */
     461             :   virtual uint32_t maxHeadersKb() const PURE;
     462             : 
     463             :   /**
     464             :    * @return uint32_t the max count of headers in a header map.
     465             :    */
     466             :   virtual uint32_t maxHeadersCount() const PURE;
     467             : 
     468             :   /**
     469             :    * This is a wrapper for the return result from get(). It avoids a copy when translating from
     470             :    * non-const HeaderEntry to const HeaderEntry and only provides const access to the result.
     471             :    */
     472             :   using NonConstGetResult = absl::InlinedVector<HeaderEntry*, 1>;
     473             :   class GetResult {
     474             :   public:
     475           0 :     GetResult() = default;
     476        6772 :     explicit GetResult(NonConstGetResult&& result) : result_(std::move(result)) {}
     477           0 :     void operator=(GetResult&& rhs) noexcept { result_ = std::move(rhs.result_); }
     478             : 
     479       10497 :     bool empty() const { return result_.empty(); }
     480       66461 :     size_t size() const { return result_.size(); }
     481       68679 :     const HeaderEntry* operator[](size_t i) const { return result_[i]; }
     482             : 
     483             :   private:
     484             :     NonConstGetResult result_;
     485             :   };
     486             : 
     487             :   /**
     488             :    * Get a header by key.
     489             :    * @param key supplies the header key.
     490             :    * @return all header entries matching the key.
     491             :    */
     492             :   virtual GetResult get(const LowerCaseString& key) const PURE;
     493             : 
     494             :   // aliases to make iterate() and iterateReverse() callbacks easier to read
     495             :   enum class Iterate { Continue, Break };
     496             : 
     497             :   /**
     498             :    * Callback when calling iterate() over a const header map.
     499             :    * @param header supplies the header entry.
     500             :    * @return Iterate::Continue to continue iteration, or Iterate::Break to stop;
     501             :    */
     502             :   using ConstIterateCb = std::function<Iterate(const HeaderEntry&)>;
     503             : 
     504             :   /**
     505             :    * Iterate over a constant header map.
     506             :    * @param cb supplies the iteration callback.
     507             :    */
     508             :   virtual void iterate(ConstIterateCb cb) const PURE;
     509             : 
     510             :   /**
     511             :    * Iterate over a constant header map in reverse order.
     512             :    * @param cb supplies the iteration callback.
     513             :    */
     514             :   virtual void iterateReverse(ConstIterateCb cb) const PURE;
     515             : 
     516             :   /**
     517             :    * Clears the headers in the map.
     518             :    */
     519             :   virtual void clear() PURE;
     520             : 
     521             :   /**
     522             :    * Remove all instances of a header by key.
     523             :    * @param key supplies the header key to remove.
     524             :    * @return the number of headers removed.
     525             :    */
     526             :   virtual size_t remove(const LowerCaseString& key) PURE;
     527             : 
     528             :   /**
     529             :    * Remove all instances of headers where the header matches the predicate.
     530             :    * @param predicate supplies the predicate to match headers against.
     531             :    * @return the number of headers removed.
     532             :    */
     533             :   using HeaderMatchPredicate = std::function<bool(const HeaderEntry&)>;
     534             :   virtual size_t removeIf(const HeaderMatchPredicate& predicate) PURE;
     535             : 
     536             :   /**
     537             :    * Remove all instances of headers where the key begins with the supplied prefix.
     538             :    * @param prefix supplies the prefix to match header keys against.
     539             :    * @return the number of headers removed.
     540             :    */
     541             :   virtual size_t removePrefix(const LowerCaseString& prefix) PURE;
     542             : 
     543             :   /**
     544             :    * @return the number of headers in the map.
     545             :    */
     546             :   virtual size_t size() const PURE;
     547             : 
     548             :   /**
     549             :    * @return true if the map is empty, false otherwise.
     550             :    */
     551             :   virtual bool empty() const PURE;
     552             : 
     553             :   /**
     554             :    * Dump the header map to the ostream specified
     555             :    *
     556             :    * @param os the stream to dump state to
     557             :    * @param indent_level the depth, for pretty-printing.
     558             :    *
     559             :    * This function is called on Envoy fatal errors so should avoid memory allocation where possible.
     560             :    */
     561             :   virtual void dumpState(std::ostream& os, int indent_level = 0) const PURE;
     562             : 
     563             :   /**
     564             :    * Allow easy pretty-printing of the key/value pairs in HeaderMap
     565             :    * @param os supplies the ostream to print to.
     566             :    * @param headers the headers to print.
     567             :    */
     568           0 :   friend std::ostream& operator<<(std::ostream& os, const HeaderMap& headers) {
     569           0 :     headers.dumpState(os);
     570           0 :     return os;
     571           0 :   }
     572             : 
     573             :   /**
     574             :    * Return the optional stateful formatter attached to this header map.
     575             :    *
     576             :    * Filters can use the non-const version to process additional header keys during operation if
     577             :    * they wish. The sequence of events would be to first add/modify the header map, and then call
     578             :    * processKey(), similar to what is done when headers are received by the codec.
     579             :    *
     580             :    * TODO(mattklein123): The above sequence will not work for headers added via route (headers to
     581             :    * add, etc.). We can potentially add direct processKey() calls in these places as a follow up.
     582             :    */
     583             :   virtual StatefulHeaderKeyFormatterOptConstRef formatter() const PURE;
     584             :   virtual StatefulHeaderKeyFormatterOptRef formatter() PURE;
     585             : };
     586             : 
     587             : using HeaderMapPtr = std::unique_ptr<HeaderMap>;
     588             : 
     589             : /**
     590             :  * Wraps a set of header modifications.
     591             :  */
     592             : struct HeaderTransforms {
     593             :   std::vector<std::pair<Http::LowerCaseString, std::string>> headers_to_append_or_add;
     594             :   std::vector<std::pair<Http::LowerCaseString, std::string>> headers_to_overwrite_or_add;
     595             :   std::vector<std::pair<Http::LowerCaseString, std::string>> headers_to_add_if_absent;
     596             :   std::vector<Http::LowerCaseString> headers_to_remove;
     597             : };
     598             : 
     599             : /**
     600             :  * Registry for custom headers. Headers can be registered multiple times in independent
     601             :  * compilation units and will still point to the same slot. Headers are registered independently
     602             :  * for each concrete header map type and do not overlap. Handles are strongly typed and do not
     603             :  * allow mixing.
     604             :  */
     605             : class CustomInlineHeaderRegistry {
     606             : public:
     607             :   enum class Type { RequestHeaders, RequestTrailers, ResponseHeaders, ResponseTrailers };
     608             :   using RegistrationMap = std::map<LowerCaseString, size_t>;
     609             : 
     610             :   // A "phantom" type is used here to force the compiler to verify that handles are not mixed
     611             :   // between concrete header map types.
     612             :   template <Type type> struct Handle {
     613        4224 :     Handle(RegistrationMap::const_iterator it) : it_(it) {}
     614             :     bool operator==(const Handle& rhs) const { return it_ == rhs.it_; }
     615             : 
     616             :     RegistrationMap::const_iterator it_;
     617             :   };
     618             : 
     619             :   /**
     620             :    * Register an inline header and return a handle for use in inline header calls. Must be called
     621             :    * prior to finalize().
     622             :    */
     623             :   template <Type type>
     624        2407 :   static Handle<type> registerInlineHeader(const LowerCaseString& header_name) {
     625        2407 :     static size_t inline_header_index = 0;
     626             : 
     627        2407 :     ASSERT(!mutableFinalized<type>());
     628        2407 :     auto& map = mutableRegistrationMap<type>();
     629        2407 :     auto entry = map.find(header_name);
     630        2407 :     if (entry == map.end()) {
     631        2358 :       map[header_name] = inline_header_index++;
     632        2358 :     }
     633        2407 :     return Handle<type>(map.find(header_name));
     634        2407 :   }
     635             : 
     636             :   /**
     637             :    * Fetch the handle for a registered inline header. May only be called after finalized().
     638             :    */
     639             :   template <Type type>
     640        1817 :   static absl::optional<Handle<type>> getInlineHeader(const LowerCaseString& header_name) {
     641        1817 :     ASSERT(mutableFinalized<type>());
     642        1817 :     auto& map = mutableRegistrationMap<type>();
     643        1817 :     auto entry = map.find(header_name);
     644        1817 :     if (entry != map.end()) {
     645        1817 :       return Handle<type>(entry);
     646        1817 :     }
     647           0 :     return absl::nullopt;
     648        1817 :   }
     649             : 
     650             :   /**
     651             :    * Fetch all registered headers. May only be called after finalized().
     652             :    */
     653         637 :   template <Type type> static const RegistrationMap& headers() {
     654         637 :     ASSERT(mutableFinalized<type>());
     655         637 :     return mutableRegistrationMap<type>();
     656         637 :   }
     657             : 
     658             :   /**
     659             :    * Finalize the custom header registrations. No further changes are allowed after this point.
     660             :    * This guaranteed that all header maps created by the process have the same variable size and
     661             :    * custom registrations.
     662             :    */
     663         101 :   template <Type type> static void finalize() {
     664         101 :     ASSERT(!mutableFinalized<type>());
     665         101 :     mutableFinalized<type>() = true;
     666         101 :   }
     667             : 
     668             : private:
     669        4861 :   template <Type type> static RegistrationMap& mutableRegistrationMap() {
     670        4861 :     MUTABLE_CONSTRUCT_ON_FIRST_USE(RegistrationMap);
     671        4861 :   }
     672         101 :   template <Type type> static bool& mutableFinalized() { MUTABLE_CONSTRUCT_ON_FIRST_USE(bool); }
     673             : };
     674             : 
     675             : /**
     676             :  * Static initializer to register a custom header in a compilation unit. This can be used by
     677             :  * extensions to register custom headers.
     678             :  */
     679             : template <CustomInlineHeaderRegistry::Type type> class RegisterCustomInlineHeader {
     680             : public:
     681             :   RegisterCustomInlineHeader(const LowerCaseString& header)
     682         153 :       : handle_(CustomInlineHeaderRegistry::registerInlineHeader<type>(header)) {}
     683             : 
     684          11 :   typename CustomInlineHeaderRegistry::Handle<type> handle() { return handle_; }
     685             : 
     686             : private:
     687             :   const typename CustomInlineHeaderRegistry::Handle<type> handle_;
     688             : };
     689             : 
     690             : /**
     691             :  * The following functions allow O(1) access for custom inline headers.
     692             :  */
     693             : template <CustomInlineHeaderRegistry::Type type> class CustomInlineHeaderBase {
     694             : public:
     695       14120 :   virtual ~CustomInlineHeaderBase() = default;
     696             : 
     697             :   static constexpr CustomInlineHeaderRegistry::Type header_map_type = type;
     698             :   using Handle = CustomInlineHeaderRegistry::Handle<header_map_type>;
     699             : 
     700             :   virtual const HeaderEntry* getInline(Handle handle) const PURE;
     701             :   virtual void appendInline(Handle handle, absl::string_view data,
     702             :                             absl::string_view delimiter) PURE;
     703             :   virtual void setReferenceInline(Handle, absl::string_view value) PURE;
     704             :   virtual void setInline(Handle, absl::string_view value) PURE;
     705             :   virtual void setInline(Handle, uint64_t value) PURE;
     706             :   virtual size_t removeInline(Handle handle) PURE;
     707       16037 :   absl::string_view getInlineValue(Handle handle) const {
     708       16037 :     const auto header = getInline(handle);
     709       16037 :     if (header != nullptr) {
     710       12029 :       return header->value().getStringView();
     711       12029 :     }
     712        4008 :     return {};
     713       16037 :   }
     714             : };
     715             : 
     716             : /**
     717             :  * Typed derived classes for all header map types.
     718             :  */
     719             : 
     720             : // Base class for both request and response headers.
     721             : class RequestOrResponseHeaderMap : public HeaderMap {
     722             : public:
     723             :   INLINE_REQ_RESP_STRING_HEADERS(DEFINE_INLINE_STRING_HEADER)
     724             :   INLINE_REQ_RESP_NUMERIC_HEADERS(DEFINE_INLINE_NUMERIC_HEADER)
     725             : };
     726             : 
     727             : // Request headers.
     728             : class RequestHeaderMap
     729             :     : public RequestOrResponseHeaderMap,
     730             :       public CustomInlineHeaderBase<CustomInlineHeaderRegistry::Type::RequestHeaders> {
     731             : public:
     732             :   INLINE_REQ_STRING_HEADERS(DEFINE_INLINE_STRING_HEADER)
     733             :   INLINE_REQ_NUMERIC_HEADERS(DEFINE_INLINE_NUMERIC_HEADER)
     734             : };
     735             : using RequestHeaderMapPtr = std::unique_ptr<RequestHeaderMap>;
     736             : using RequestHeaderMapSharedPtr = std::shared_ptr<RequestHeaderMap>;
     737             : using RequestHeaderMapConstSharedPtr = std::shared_ptr<const RequestHeaderMap>;
     738             : using RequestHeaderMapOptRef = OptRef<RequestHeaderMap>;
     739             : using RequestHeaderMapOptConstRef = OptRef<const RequestHeaderMap>;
     740             : 
     741             : // Request trailers.
     742             : class RequestTrailerMap
     743             :     : public HeaderMap,
     744             :       public CustomInlineHeaderBase<CustomInlineHeaderRegistry::Type::RequestTrailers> {};
     745             : using RequestTrailerMapPtr = std::unique_ptr<RequestTrailerMap>;
     746             : using RequestTrailerMapOptRef = OptRef<RequestTrailerMap>;
     747             : using RequestTrailerMapOptConstRef = OptRef<const RequestTrailerMap>;
     748             : 
     749             : // Base class for both response headers and trailers.
     750             : class ResponseHeaderOrTrailerMap {
     751             : public:
     752        4600 :   virtual ~ResponseHeaderOrTrailerMap() = default;
     753             : 
     754             :   INLINE_RESP_STRING_HEADERS_TRAILERS(DEFINE_INLINE_STRING_HEADER)
     755             :   INLINE_RESP_NUMERIC_HEADERS_TRAILERS(DEFINE_INLINE_NUMERIC_HEADER)
     756             : };
     757             : 
     758             : // Response headers.
     759             : class ResponseHeaderMap
     760             :     : public RequestOrResponseHeaderMap,
     761             :       public ResponseHeaderOrTrailerMap,
     762             :       public CustomInlineHeaderBase<CustomInlineHeaderRegistry::Type::ResponseHeaders> {
     763             : public:
     764             :   INLINE_RESP_STRING_HEADERS(DEFINE_INLINE_STRING_HEADER)
     765             :   INLINE_RESP_NUMERIC_HEADERS(DEFINE_INLINE_NUMERIC_HEADER)
     766             : };
     767             : using ResponseHeaderMapPtr = std::unique_ptr<ResponseHeaderMap>;
     768             : using ResponseHeaderMapSharedPtr = std::shared_ptr<ResponseHeaderMap>;
     769             : using ResponseHeaderMapConstSharedPtr = std::shared_ptr<const ResponseHeaderMap>;
     770             : using ResponseHeaderMapOptRef = OptRef<ResponseHeaderMap>;
     771             : using ResponseHeaderMapOptConstRef = OptRef<const ResponseHeaderMap>;
     772             : 
     773             : // Response trailers.
     774             : class ResponseTrailerMap
     775             :     : public ResponseHeaderOrTrailerMap,
     776             :       public HeaderMap,
     777             :       public CustomInlineHeaderBase<CustomInlineHeaderRegistry::Type::ResponseTrailers> {};
     778             : using ResponseTrailerMapPtr = std::unique_ptr<ResponseTrailerMap>;
     779             : using ResponseTrailerMapSharedPtr = std::shared_ptr<ResponseTrailerMap>;
     780             : using ResponseTrailerMapConstSharedPtr = std::shared_ptr<const ResponseTrailerMap>;
     781             : using ResponseTrailerMapOptRef = OptRef<ResponseTrailerMap>;
     782             : using ResponseTrailerMapOptConstRef = OptRef<const ResponseTrailerMap>;
     783             : 
     784             : /**
     785             :  * Convenient container type for storing Http::LowerCaseString and std::string key/value pairs.
     786             :  */
     787             : using HeaderVector = std::vector<std::pair<LowerCaseString, std::string>>;
     788             : 
     789             : /**
     790             :  * An interface to be implemented by header matchers.
     791             :  */
     792             : class HeaderMatcher {
     793             : public:
     794          72 :   virtual ~HeaderMatcher() = default;
     795             : 
     796             :   /**
     797             :    * Check whether header matcher matches any headers in a given HeaderMap.
     798             :    */
     799             :   virtual bool matchesHeaders(const HeaderMap& headers) const PURE;
     800             : };
     801             : 
     802             : using HeaderMatcherSharedPtr = std::shared_ptr<HeaderMatcher>;
     803             : 
     804             : } // namespace Http
     805             : } // namespace Envoy
     806             : 
     807             : // NOLINT(namespace-envoy)
     808             : namespace fmt {
     809             : // Allow fmtlib to use operator << defined in HeaderMap and LowerCaseString
     810             : template <> struct formatter<::Envoy::Http::LowerCaseString> : ostream_formatter {};
     811             : 
     812             : template <typename HeaderMapType>
     813             : struct formatter<
     814             :     HeaderMapType,
     815             :     std::enable_if_t<std::is_base_of<::Envoy::Http::HeaderMap, HeaderMapType>::value, char>>
     816             :     : ostream_formatter {};
     817             : } // namespace fmt

Generated by: LCOV version 1.15