1
#pragma once
2

            
3
#include <algorithm>
4
#include <cstdint>
5
#include <cstring>
6
#include <iosfwd>
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
#include "envoy/stream_info/filter_state.h"
17

            
18
#include "source/common/common/assert.h"
19
#include "source/common/common/hash.h"
20
#include "source/common/common/macros.h"
21

            
22
#include "absl/container/inlined_vector.h"
23
#include "absl/strings/string_view.h"
24

            
25
namespace Envoy {
26
namespace Http {
27

            
28
// Used by ASSERTs to validate internal consistency. E.g. valid HTTP header keys/values should
29
// never contain embedded NULLs.
30
3
static inline bool validHeaderString(absl::string_view s) {
31
  // If you modify this list of illegal embedded characters you will probably
32
  // want to change header_map_fuzz_impl_test at the same time.
33
9
  for (const char c : s) {
34
9
    switch (c) {
35
1
    case '\0':
36
1
      FALLTHRU;
37
1
    case '\r':
38
1
      FALLTHRU;
39
2
    case '\n':
40
2
      return false;
41
7
    default:
42
7
      continue;
43
9
    }
44
9
  }
45
1
  return true;
46
3
}
47

            
48
/**
49
 * Wrapper for a lower case string used in header operations to generally avoid needless case
50
 * insensitive compares.
51
 */
52
class LowerCaseString {
53
public:
54
9046
  LowerCaseString(LowerCaseString&& rhs) noexcept : string_(std::move(rhs.string_)) {
55
9046
    ASSERT(valid());
56
9046
  }
57
65
  LowerCaseString& operator=(LowerCaseString&& rhs) noexcept {
58
65
    string_ = std::move(rhs.string_);
59
65
    ASSERT(valid());
60
65
    return *this;
61
65
  }
62

            
63
116766
  LowerCaseString(const LowerCaseString& rhs) : string_(rhs.string_) { ASSERT(valid()); }
64
1
  LowerCaseString& operator=(const LowerCaseString& rhs) {
65
1
    string_ = std::move(rhs.string_);
66
1
    ASSERT(valid());
67
1
    return *this;
68
1
  }
69

            
70
2346599
  explicit LowerCaseString(absl::string_view new_string) : string_(new_string) {
71
2346599
    ASSERT(valid());
72
2346599
    lower();
73
2346599
  }
74

            
75
15930739
  const std::string& get() const { return string_; }
76
41194
  bool operator==(const LowerCaseString& rhs) const { return string_ == rhs.string_; }
77
107256
  bool operator!=(const LowerCaseString& rhs) const { return string_ != rhs.string_; }
78
1491666
  bool operator<(const LowerCaseString& rhs) const { return string_.compare(rhs.string_) < 0; }
79

            
80
8
  friend std::ostream& operator<<(std::ostream& os, const LowerCaseString& lower_case_string) {
81
8
    return os << lower_case_string.string_;
82
8
  }
83

            
84
  // Implicit conversion to absl::string_view.
85
1567298
  operator absl::string_view() const { return string_; }
86

            
87
private:
88
2346599
  void lower() {
89
2346599
    std::transform(string_.begin(), string_.end(), string_.begin(), absl::ascii_tolower);
90
2346599
  }
91
  bool valid() const { return validHeaderString(string_); }
92

            
93
  std::string string_;
94
};
95

            
96
/**
97
 * Convenient type for a vector of lower case string and string pair.
98
 */
99
using LowerCaseStrPairVector =
100
    std::vector<std::pair<const Http::LowerCaseString, const std::string>>;
101

            
102
class HeaderStringValidator {
103
public:
104
  bool operator()(absl::string_view view) {
105
    return disable_validation_for_tests_ ? true : validHeaderString(view);
106
  }
107

            
108
  // This flag allows disabling the check for the NUL, CR and LF characters in the
109
  // header names or values in the DEBUG builds to prevent the `ASSERT(valid())` in the
110
  // HeaderString constructor from failing tests.
111
  static bool disable_validation_for_tests_;
112
};
113

            
114
class HeaderString : public UnionStringBase<HeaderStringValidator> {
115
public:
116
  using UnionStringBase::UnionStringBase;
117

            
118
  /**
119
   * Constructor for a lower case string reference.
120
   * @param ref_value MUST point to data that will live beyond the lifetime of any request/response
121
   *        using the string (since a codec may optimize for zero copy).
122
   */
123
  explicit HeaderString(const LowerCaseString& ref_value) noexcept;
124

            
125
  /**
126
   * Constructor for normal UnionString instance.
127
   * @param move_value moveable UnionString. The string value MUST be valid header string.
128
   */
129
  explicit HeaderString(UnionString&& move_value) noexcept;
130
};
131

            
132
/**
133
 * Encapsulates an individual header entry (including both key and value).
134
 */
135
class HeaderEntry {
136
public:
137
3831321
  virtual ~HeaderEntry() = default;
138

            
139
  /**
140
   * @return the header key.
141
   */
142
  virtual const HeaderString& key() const PURE;
143

            
144
  /**
145
   * Set the header value by copying data into it.
146
   */
147
  virtual void value(absl::string_view value) PURE;
148

            
149
  /**
150
   * Set the header value by copying an integer into it.
151
   */
152
  virtual void value(uint64_t value) PURE;
153

            
154
  /**
155
   * Set the header value by copying the value in another header entry.
156
   */
157
  virtual void value(const HeaderEntry& header) PURE;
158

            
159
  /**
160
   * @return the header value.
161
   */
162
  virtual const HeaderString& value() const PURE;
163

            
164
  /**
165
   * @return the header value.
166
   */
167
  virtual HeaderString& value() PURE;
168

            
169
private:
170
  void value(const char*); // Do not allow auto conversion to std::string
171
};
172

            
173
/**
174
 * The following defines all default request headers that Envoy allows direct access to inside of
175
 * the header map. In practice, these are all headers used during normal Envoy request flow
176
 * processing. This allows O(1) access to these headers without even a hash lookup.
177
 *
178
 */
179
#define INLINE_REQ_STRING_HEADERS(HEADER_FUNC)                                                     \
180
870
  HEADER_FUNC(ClientTraceId)                                                                       \
181
870
  HEADER_FUNC(EnvoyDownstreamServiceCluster)                                                       \
182
870
  HEADER_FUNC(EnvoyDownstreamServiceNode)                                                          \
183
870
  HEADER_FUNC(EnvoyExternalAddress)                                                                \
184
870
  HEADER_FUNC(EnvoyForceTrace)                                                                     \
185
870
  HEADER_FUNC(EnvoyHedgeOnPerTryTimeout)                                                           \
186
870
  HEADER_FUNC(EnvoyInternalRequest)                                                                \
187
870
  HEADER_FUNC(EnvoyIpTags)                                                                         \
188
870
  HEADER_FUNC(EnvoyRetryOn)                                                                        \
189
870
  HEADER_FUNC(EnvoyRetryGrpcOn)                                                                    \
190
870
  HEADER_FUNC(EnvoyRetriableStatusCodes)                                                           \
191
870
  HEADER_FUNC(EnvoyRetriableHeaderNames)                                                           \
192
870
  HEADER_FUNC(EnvoyIsTimeoutRetry)                                                                 \
193
870
  HEADER_FUNC(EnvoyOriginalPath)                                                                   \
194
870
  HEADER_FUNC(EnvoyOriginalHost)                                                                   \
195
870
  HEADER_FUNC(EnvoyOriginalUrl)                                                                    \
196
870
  HEADER_FUNC(EnvoyUpstreamAltStatName)                                                            \
197
870
  HEADER_FUNC(EnvoyUpstreamRequestTimeoutAltResponse)                                              \
198
870
  HEADER_FUNC(Expect)                                                                              \
199
870
  HEADER_FUNC(ForwardedClientCert)                                                                 \
200
870
  HEADER_FUNC(ForwardedFor)                                                                        \
201
870
  HEADER_FUNC(ForwardedHost)                                                                       \
202
870
  HEADER_FUNC(ForwardedProto)                                                                      \
203
870
  HEADER_FUNC(GrpcTimeout)                                                                         \
204
870
  HEADER_FUNC(Host)                                                                                \
205
870
  HEADER_FUNC(Method)                                                                              \
206
870
  HEADER_FUNC(Path)                                                                                \
207
870
  HEADER_FUNC(Protocol)                                                                            \
208
870
  HEADER_FUNC(Scheme)                                                                              \
209
870
  HEADER_FUNC(TE)                                                                                  \
210
870
  HEADER_FUNC(UserAgent)
211

            
212
#define INLINE_REQ_NUMERIC_HEADERS(HEADER_FUNC)                                                    \
213
869
  HEADER_FUNC(EnvoyExpectedRequestTimeoutMs)                                                       \
214
869
  HEADER_FUNC(EnvoyMaxRetries)                                                                     \
215
869
  HEADER_FUNC(EnvoyUpstreamRequestTimeoutMs)                                                       \
216
869
  HEADER_FUNC(EnvoyUpstreamRequestPerTryTimeoutMs)                                                 \
217
869
  HEADER_FUNC(EnvoyUpstreamStreamDurationMs)                                                       \
218
869
  HEADER_FUNC(ForwardedPort)
219

            
220
#define INLINE_REQ_HEADERS(HEADER_FUNC)                                                            \
221
869
  INLINE_REQ_STRING_HEADERS(HEADER_FUNC)                                                           \
222
869
  INLINE_REQ_NUMERIC_HEADERS(HEADER_FUNC)
223

            
224
/**
225
 * Default O(1) response headers.
226
 */
227
#define INLINE_RESP_STRING_HEADERS(HEADER_FUNC)                                                    \
228
773
  HEADER_FUNC(Date)                                                                                \
229
773
  HEADER_FUNC(EnvoyDegraded)                                                                       \
230
773
  HEADER_FUNC(EnvoyImmediateHealthCheckFail)                                                       \
231
773
  HEADER_FUNC(EnvoyRateLimited)                                                                    \
232
773
  HEADER_FUNC(EnvoyUpstreamCanary)                                                                 \
233
773
  HEADER_FUNC(EnvoyUpstreamHealthCheckedCluster)                                                   \
234
773
  HEADER_FUNC(Location)                                                                            \
235
773
  HEADER_FUNC(Server)
236

            
237
#define INLINE_RESP_NUMERIC_HEADERS(HEADER_FUNC)                                                   \
238
772
  HEADER_FUNC(EnvoyUpstreamServiceTime)                                                            \
239
772
  HEADER_FUNC(Status)
240

            
241
#define INLINE_RESP_HEADERS(HEADER_FUNC)                                                           \
242
772
  INLINE_RESP_STRING_HEADERS(HEADER_FUNC)                                                          \
243
772
  INLINE_RESP_NUMERIC_HEADERS(HEADER_FUNC)
244

            
245
/**
246
 * Default O(1) request and response headers.
247
 */
248
#define INLINE_REQ_RESP_STRING_HEADERS(HEADER_FUNC)                                                \
249
1643
  HEADER_FUNC(Connection)                                                                          \
250
1643
  HEADER_FUNC(ContentType)                                                                         \
251
1643
  HEADER_FUNC(EnvoyDecoratorOperation)                                                             \
252
1643
  HEADER_FUNC(KeepAlive)                                                                           \
253
1643
  HEADER_FUNC(ProxyConnection)                                                                     \
254
1643
  HEADER_FUNC(ProxyStatus)                                                                         \
255
1643
  HEADER_FUNC(RequestId)                                                                           \
256
1643
  HEADER_FUNC(TransferEncoding)                                                                    \
257
1643
  HEADER_FUNC(Upgrade)                                                                             \
258
1643
  HEADER_FUNC(Via)
259

            
260
#define INLINE_REQ_RESP_NUMERIC_HEADERS(HEADER_FUNC)                                               \
261
1641
  HEADER_FUNC(ContentLength)                                                                       \
262
1641
  HEADER_FUNC(EnvoyAttemptCount)
263

            
264
#define INLINE_REQ_RESP_HEADERS(HEADER_FUNC)                                                       \
265
1641
  INLINE_REQ_RESP_STRING_HEADERS(HEADER_FUNC)                                                      \
266
1641
  INLINE_REQ_RESP_NUMERIC_HEADERS(HEADER_FUNC)
267

            
268
/**
269
 * Default O(1) response headers and trailers.
270
 */
271
1382
#define INLINE_RESP_STRING_HEADERS_TRAILERS(HEADER_FUNC) HEADER_FUNC(GrpcMessage)
272

            
273
1380
#define INLINE_RESP_NUMERIC_HEADERS_TRAILERS(HEADER_FUNC) HEADER_FUNC(GrpcStatus)
274

            
275
#define INLINE_RESP_HEADERS_TRAILERS(HEADER_FUNC)                                                  \
276
1380
  INLINE_RESP_STRING_HEADERS_TRAILERS(HEADER_FUNC)                                                 \
277
1380
  INLINE_RESP_NUMERIC_HEADERS_TRAILERS(HEADER_FUNC)
278

            
279
/**
280
 * The following functions are defined for each inline header above.
281

            
282
 * E.g., for path we have:
283
 * Path() -> returns the header entry if it exists or nullptr.
284
 * removePath() -> removes the header if it exists.
285
 * setPath(path_string) -> sets the header value to the string path_string by copying the data.
286
 *
287
 */
288
#define DEFINE_INLINE_HEADER(name)                                                                 \
289
  virtual const HeaderEntry* name() const PURE;                                                    \
290
  virtual size_t remove##name() PURE;                                                              \
291
  virtual absl::string_view get##name##Value() const PURE;                                         \
292
  virtual void set##name(absl::string_view value) PURE;
293

            
294
/*
295
 * For inline headers that have string values, there are also:
296
 * appendPath(path, "/") -> appends the string path with delimiter "/" to the header value.
297
 * setReferencePath(PATH) -> sets header value to reference string PATH.
298
 *
299
 */
300
#define DEFINE_INLINE_STRING_HEADER(name)                                                          \
301
  DEFINE_INLINE_HEADER(name)                                                                       \
302
  virtual void append##name(absl::string_view data, absl::string_view delimiter) PURE;             \
303
  virtual void setReference##name(absl::string_view value) PURE;
304

            
305
/*
306
 * For inline headers that use integers, there is:
307
 * setContentLength(5) -> sets the header value to the integer 5.
308
 */
309
#define DEFINE_INLINE_NUMERIC_HEADER(name)                                                         \
310
  DEFINE_INLINE_HEADER(name)                                                                       \
311
  virtual void set##name(uint64_t) PURE;
312

            
313
/**
314
 * Wraps a set of HTTP headers.
315
 */
316
class HeaderMap {
317
public:
318
2706722
  virtual ~HeaderMap() = default;
319

            
320
  /**
321
   * For testing. This is an exact match comparison (order matters).
322
   */
323
  virtual bool operator==(const HeaderMap& rhs) const PURE;
324
  virtual bool operator!=(const HeaderMap& rhs) const PURE;
325

            
326
  /**
327
   * Add a header via full move. This is the expected high performance paths for codecs populating
328
   * a map when receiving.
329
   * @param key supplies the header key.
330
   * @param value supplies the header value.
331
   */
332
  virtual void addViaMove(HeaderString&& key, HeaderString&& value) PURE;
333

            
334
  /**
335
   * Add a reference header to the map. Both key and value MUST point to data that will live beyond
336
   * the lifetime of any request/response using the string (since a codec may optimize for zero
337
   * copy). The key will not be copied and a best effort will be made not to
338
   * copy the value (but this may happen when comma concatenating, see below).
339
   *
340
   * Calling addReference multiple times for the same header will result in:
341
   * - Comma concatenation for predefined inline headers.
342
   * - Multiple headers being present in the HeaderMap for other headers.
343
   *
344
   * @param key specifies the name of the header to add; it WILL NOT be copied.
345
   * @param value specifies the value of the header to add; it WILL NOT be copied.
346
   */
347
  virtual void addReference(const LowerCaseString& key, absl::string_view value) PURE;
348

            
349
  /**
350
   * Add a header with a reference key to the map. The key MUST point to data that will live beyond
351
   * the lifetime of any request/response using the string (since a codec may optimize for zero
352
   * copy). The value will be copied.
353
   *
354
   * Calling addReference multiple times for the same header will result in:
355
   * - Comma concatenation for predefined inline headers.
356
   * - Multiple headers being present in the HeaderMap for other headers.
357
   *
358
   * @param key specifies the name of the header to add; it WILL NOT be copied.
359
   * @param value specifies the value of the header to add; it WILL be copied.
360
   */
361
  virtual void addReferenceKey(const LowerCaseString& key, uint64_t value) PURE;
362

            
363
  /**
364
   * Add a header with a reference key to the map. The key MUST point to data that will
365
   * live beyond the lifetime of any request/response using the string (since a codec may optimize
366
   * for zero copy). The value will be copied.
367
   *
368
   * Calling addReference multiple times for the same header will result in:
369
   * - Comma concatenation for predefined inline headers.
370
   * - Multiple headers being present in the HeaderMap for other headers.
371
   *
372
   * @param key specifies the name of the header to add; it WILL NOT be copied.
373
   * @param value specifies the value of the header to add; it WILL be copied.
374
   */
375
  virtual void addReferenceKey(const LowerCaseString& key, absl::string_view value) PURE;
376

            
377
  /**
378
   * Add a header by copying both the header key and the value.
379
   *
380
   * Calling addCopy multiple times for the same header will result in:
381
   * - Comma concatenation for predefined inline headers.
382
   * - Multiple headers being present in the HeaderMap for other headers.
383
   *
384
   * @param key specifies the name of the header to add; it WILL be copied.
385
   * @param value specifies the value of the header to add; it WILL be copied.
386
   */
387
  virtual void addCopy(const LowerCaseString& key, uint64_t value) PURE;
388

            
389
  /**
390
   * Add a header by copying both the header key and the value.
391
   *
392
   * Calling addCopy multiple times for the same header will result in:
393
   * - Comma concatenation for predefined inline headers.
394
   * - Multiple headers being present in the HeaderMap for other headers.
395
   *
396
   * @param key specifies the name of the header to add; it WILL be copied.
397
   * @param value specifies the value of the header to add; it WILL be copied.
398
   */
399
  virtual void addCopy(const LowerCaseString& key, absl::string_view value) PURE;
400

            
401
  /**
402
   * Appends data to header. If header already has a value, the string "," is added between the
403
   * existing value and data.
404
   *
405
   * @param key specifies the name of the header to append; it WILL be copied.
406
   * @param value specifies the value of the header to add; it WILL be copied.
407
   *
408
   * Caution: This iterates over the HeaderMap to find the header to append. This will modify only
409
   * the first occurrence of the header.
410
   * TODO(asraa): Investigate whether necessary to append to all headers with the key.
411
   */
412
  virtual void appendCopy(const LowerCaseString& key, absl::string_view value) PURE;
413

            
414
  /**
415
   * Set a reference header in the map. Both key and value MUST point to data that will live beyond
416
   * the lifetime of any request/response using the string (since a codec may optimize for zero
417
   * copy). Nothing will be copied.
418
   *
419
   * Calling setReference multiple times for the same header will result in only the last header
420
   * being present in the HeaderMap.
421
   *
422
   * @param key specifies the name of the header to set; it WILL NOT be copied.
423
   * @param value specifies the value of the header to set; it WILL NOT be copied.
424
   */
425
  virtual void setReference(const LowerCaseString& key, absl::string_view value) PURE;
426

            
427
  /**
428
   * Set a header with a reference key in the map. The key MUST point to point to data that will
429
   * live beyond the lifetime of any request/response using the string (since a codec may optimize
430
   * for zero copy). The value will be copied.
431
   *
432
   * Calling setReferenceKey multiple times for the same header will result in only the last header
433
   * being present in the HeaderMap.
434
   *
435
   * @param key specifies the name of the header to set; it WILL NOT be copied.
436
   * @param value specifies the value of the header to set; it WILL be copied.
437
   */
438
  virtual void setReferenceKey(const LowerCaseString& key, absl::string_view value) PURE;
439

            
440
  /**
441
   * Replaces a header value by copying the value. Copies the key if the key does not exist.
442
   * If there are multiple values for one header, this removes all existing values and add
443
   * the new one.
444
   *
445
   * Calling setCopy multiple times for the same header will result in only the last header
446
   * being present in the HeaderMap.
447
   *
448
   * @param key specifies the name of the header to set; it WILL be copied.
449
   * @param value specifies the value of the header to set; it WILL be copied.
450
   * TODO(asraa): Investigate whether necessary to set all headers with the key.
451
   */
452
  virtual void setCopy(const LowerCaseString& key, absl::string_view value) PURE;
453

            
454
  /**
455
   * @return uint64_t the size of the header map in bytes. This is the sum of the header keys and
456
   * values and does not account for data structure overhead.
457
   */
458
  virtual uint64_t byteSize() const PURE;
459

            
460
  /**
461
   * @return uint32_t the max size of the header map in kilobyte.
462
   */
463
  virtual uint32_t maxHeadersKb() const PURE;
464

            
465
  /**
466
   * @return uint32_t the max count of headers in a header map.
467
   */
468
  virtual uint32_t maxHeadersCount() const PURE;
469

            
470
  // aliases to make iterate() and iterateReverse() callbacks easier to read
471
  enum class Iterate { Continue, Break };
472

            
473
  /**
474
   * Callback when calling iterate() over a const header map.
475
   * @param header supplies the header entry.
476
   * @return Iterate::Continue to continue iteration, or Iterate::Break to stop;
477
   */
478
  using ConstIterateCb = std::function<Iterate(const HeaderEntry&)>;
479

            
480
  /**
481
   * This is a wrapper for the return result from get(). It avoids a copy when translating from
482
   * non-const HeaderEntry to const HeaderEntry and only provides const access to the result.
483
   */
484
  using NonConstGetResult = absl::InlinedVector<HeaderEntry*, 1>;
485
  class GetResult {
486
  public:
487
82
    GetResult() = default;
488
810349
    explicit GetResult(NonConstGetResult&& result) : result_(std::move(result)) {}
489
175
    void operator=(GetResult&& rhs) noexcept { result_ = std::move(rhs.result_); }
490

            
491
1164424
    bool empty() const { return result_.empty(); }
492
26390
    size_t size() const { return result_.size(); }
493
332117
    const HeaderEntry* operator[](size_t i) const { return result_[i]; }
494
21
    void iterate(ConstIterateCb cb) const {
495
21
      for (const auto& val : result_) {
496
5
        if (cb(*val) == Iterate::Break) {
497
5
          break;
498
5
        }
499
5
      }
500
21
    }
501

            
502
  private:
503
    NonConstGetResult result_;
504
  };
505

            
506
  /**
507
   * Get a header by key.
508
   * @param key supplies the header key.
509
   * @return all header entries matching the key.
510
   */
511
  virtual GetResult get(const LowerCaseString& key) const PURE;
512

            
513
  /**
514
   * Iterate over a constant header map.
515
   * @param cb supplies the iteration callback.
516
   */
517
  virtual void iterate(ConstIterateCb cb) const PURE;
518

            
519
  /**
520
   * Iterate over a constant header map in reverse order.
521
   * @param cb supplies the iteration callback.
522
   */
523
  virtual void iterateReverse(ConstIterateCb cb) const PURE;
524

            
525
  /**
526
   * Clears the headers in the map.
527
   */
528
  virtual void clear() PURE;
529

            
530
  /**
531
   * Remove all instances of a header by key.
532
   * @param key supplies the header key to remove.
533
   * @return the number of headers removed.
534
   */
535
  virtual size_t remove(const LowerCaseString& key) PURE;
536

            
537
  /**
538
   * Remove all instances of headers where the header matches the predicate.
539
   * @param predicate supplies the predicate to match headers against.
540
   * @return the number of headers removed.
541
   */
542
  using HeaderMatchPredicate = std::function<bool(const HeaderEntry&)>;
543
  virtual size_t removeIf(const HeaderMatchPredicate& predicate) PURE;
544

            
545
  /**
546
   * Remove all instances of headers where the key begins with the supplied prefix.
547
   * @param prefix supplies the prefix to match header keys against.
548
   * @return the number of headers removed.
549
   */
550
  virtual size_t removePrefix(const LowerCaseString& prefix) PURE;
551

            
552
  /**
553
   * @return the number of headers in the map.
554
   */
555
  virtual size_t size() const PURE;
556

            
557
  /**
558
   * @return true if the map is empty, false otherwise.
559
   */
560
  virtual bool empty() const PURE;
561

            
562
  /**
563
   * Dump the header map to the ostream specified
564
   *
565
   * @param os the stream to dump state to
566
   * @param indent_level the depth, for pretty-printing.
567
   *
568
   * This function is called on Envoy fatal errors so should avoid memory allocation where possible.
569
   */
570
  virtual void dumpState(std::ostream& os, int indent_level = 0) const PURE;
571

            
572
  /**
573
   * Allow easy pretty-printing of the key/value pairs in HeaderMap
574
   * @param os supplies the ostream to print to.
575
   * @param headers the headers to print.
576
   */
577
541
  friend std::ostream& operator<<(std::ostream& os, const HeaderMap& headers) {
578
541
    headers.dumpState(os);
579
541
    return os;
580
541
  }
581

            
582
  /**
583
   * Return the optional stateful formatter attached to this header map.
584
   *
585
   * Filters can use the non-const version to process additional header keys during operation if
586
   * they wish. The sequence of events would be to first add/modify the header map, and then call
587
   * processKey(), similar to what is done when headers are received by the codec.
588
   *
589
   * TODO(mattklein123): The above sequence will not work for headers added via route (headers to
590
   * add, etc.). We can potentially add direct processKey() calls in these places as a follow up.
591
   */
592
  virtual StatefulHeaderKeyFormatterOptConstRef formatter() const PURE;
593
  virtual StatefulHeaderKeyFormatterOptRef formatter() PURE;
594
};
595

            
596
using HeaderMapPtr = std::unique_ptr<HeaderMap>;
597

            
598
/**
599
 * Wraps a set of header modifications.
600
 */
601
struct HeaderTransforms {
602
  std::vector<std::pair<Http::LowerCaseString, std::string>> headers_to_append_or_add;
603
  std::vector<std::pair<Http::LowerCaseString, std::string>> headers_to_overwrite_or_add;
604
  std::vector<std::pair<Http::LowerCaseString, std::string>> headers_to_add_if_absent;
605
  std::vector<Http::LowerCaseString> headers_to_remove;
606
};
607

            
608
/**
609
 * Registry for custom headers. Headers can be registered multiple times in independent
610
 * compilation units and will still point to the same slot. Headers are registered independently
611
 * for each concrete header map type and do not overlap. Handles are strongly typed and do not
612
 * allow mixing.
613
 */
614
class CustomInlineHeaderRegistry {
615
public:
616
  enum class Type { RequestHeaders, RequestTrailers, ResponseHeaders, ResponseTrailers };
617
  using RegistrationMap = std::map<LowerCaseString, size_t>;
618

            
619
  // A "phantom" type is used here to force the compiler to verify that handles are not mixed
620
  // between concrete header map types.
621
  template <Type type> struct Handle {
622
112314
    Handle(RegistrationMap::const_iterator it) : it_(it) {}
623
1
    bool operator==(const Handle& rhs) const { return it_ == rhs.it_; }
624

            
625
    RegistrationMap::const_iterator it_;
626
  };
627

            
628
  /**
629
   * Register an inline header and return a handle for use in inline header calls. Must be called
630
   * prior to finalize().
631
   */
632
  template <Type type>
633
63239
  static Handle<type> registerInlineHeader(const LowerCaseString& header_name) {
634
63239
    static size_t inline_header_index = 0;
635

            
636
63239
    ASSERT(!mutableFinalized<type>());
637
63239
    auto& map = mutableRegistrationMap<type>();
638
63239
    auto entry = map.find(header_name);
639
63239
    if (entry == map.end()) {
640
63142
      map[header_name] = inline_header_index++;
641
63142
    }
642
63239
    return Handle<type>(map.find(header_name));
643
63239
  }
644

            
645
  /**
646
   * Fetch the handle for a registered inline header. May only be called after finalized().
647
   */
648
  template <Type type>
649
49170
  static absl::optional<Handle<type>> getInlineHeader(const LowerCaseString& header_name) {
650
49170
    ASSERT(mutableFinalized<type>());
651
49170
    auto& map = mutableRegistrationMap<type>();
652
49170
    auto entry = map.find(header_name);
653
49170
    if (entry != map.end()) {
654
49075
      return Handle<type>(entry);
655
49075
    }
656
95
    return absl::nullopt;
657
49170
  }
658

            
659
  /**
660
   * Fetch all registered headers. May only be called after finalized().
661
   */
662
45514
  template <Type type> static const RegistrationMap& headers() {
663
45514
    ASSERT(mutableFinalized<type>());
664
45514
    return mutableRegistrationMap<type>();
665
45514
  }
666

            
667
  /**
668
   * Finalize the custom header registrations. No further changes are allowed after this point.
669
   * This guaranteed that all header maps created by the process have the same variable size and
670
   * custom registrations.
671
   */
672
2830
  template <Type type> static void finalize() {
673
2830
    ASSERT(!mutableFinalized<type>());
674
2830
    mutableFinalized<type>() = true;
675
2830
  }
676

            
677
private:
678
157923
  template <Type type> static RegistrationMap& mutableRegistrationMap() {
679
157923
    MUTABLE_CONSTRUCT_ON_FIRST_USE(RegistrationMap);
680
157923
  }
681
2830
  template <Type type> static bool& mutableFinalized() { MUTABLE_CONSTRUCT_ON_FIRST_USE(bool); }
682
};
683

            
684
/**
685
 * Static initializer to register a custom header in a compilation unit. This can be used by
686
 * extensions to register custom headers.
687
 */
688
template <CustomInlineHeaderRegistry::Type type> class RegisterCustomInlineHeader {
689
public:
690
  RegisterCustomInlineHeader(const LowerCaseString& header)
691
908
      : handle_(CustomInlineHeaderRegistry::registerInlineHeader<type>(header)) {}
692

            
693
6040
  typename CustomInlineHeaderRegistry::Handle<type> handle() const { return handle_; }
694

            
695
private:
696
  const typename CustomInlineHeaderRegistry::Handle<type> handle_;
697
};
698

            
699
/**
700
 * The following functions allow O(1) access for custom inline headers.
701
 */
702
template <CustomInlineHeaderRegistry::Type type> class CustomInlineHeaderBase {
703
public:
704
2706723
  virtual ~CustomInlineHeaderBase() = default;
705

            
706
  static constexpr CustomInlineHeaderRegistry::Type header_map_type = type;
707
  using Handle = CustomInlineHeaderRegistry::Handle<header_map_type>;
708

            
709
  virtual const HeaderEntry* getInline(Handle handle) const PURE;
710
  virtual void appendInline(Handle handle, absl::string_view data,
711
                            absl::string_view delimiter) PURE;
712
  virtual void setReferenceInline(Handle, absl::string_view value) PURE;
713
  virtual void setInline(Handle, absl::string_view value) PURE;
714
  virtual void setInline(Handle, uint64_t value) PURE;
715
  virtual size_t removeInline(Handle handle) PURE;
716
6542585
  absl::string_view getInlineValue(Handle handle) const {
717
6542585
    const auto header = getInline(handle);
718
6542585
    if (header != nullptr) {
719
6068594
      return header->value().getStringView();
720
6068594
    }
721
473991
    return {};
722
6542585
  }
723
};
724

            
725
/**
726
 * Typed derived classes for all header map types.
727
 */
728

            
729
// Base class for both request and response headers.
730
class RequestOrResponseHeaderMap : public HeaderMap {
731
public:
732
  INLINE_REQ_RESP_STRING_HEADERS(DEFINE_INLINE_STRING_HEADER)
733
  INLINE_REQ_RESP_NUMERIC_HEADERS(DEFINE_INLINE_NUMERIC_HEADER)
734
};
735

            
736
// Request headers.
737
class RequestHeaderMap
738
    : public RequestOrResponseHeaderMap,
739
      public CustomInlineHeaderBase<CustomInlineHeaderRegistry::Type::RequestHeaders> {
740
public:
741
  INLINE_REQ_STRING_HEADERS(DEFINE_INLINE_STRING_HEADER)
742
  INLINE_REQ_NUMERIC_HEADERS(DEFINE_INLINE_NUMERIC_HEADER)
743
};
744
using RequestHeaderMapPtr = std::unique_ptr<RequestHeaderMap>;
745
using RequestHeaderMapSharedPtr = std::shared_ptr<RequestHeaderMap>;
746
using RequestHeaderMapConstSharedPtr = std::shared_ptr<const RequestHeaderMap>;
747
using RequestHeaderMapOptRef = OptRef<RequestHeaderMap>;
748
using RequestHeaderMapOptConstRef = OptRef<const RequestHeaderMap>;
749

            
750
// Request trailers.
751
class RequestTrailerMap
752
    : public HeaderMap,
753
      public CustomInlineHeaderBase<CustomInlineHeaderRegistry::Type::RequestTrailers> {};
754
using RequestTrailerMapPtr = std::unique_ptr<RequestTrailerMap>;
755
using RequestTrailerMapSharedPtr = std::shared_ptr<RequestTrailerMap>;
756
using RequestTrailerMapConstSharedPtr = std::shared_ptr<const RequestTrailerMap>;
757
using RequestTrailerMapOptRef = OptRef<RequestTrailerMap>;
758
using RequestTrailerMapOptConstRef = OptRef<const RequestTrailerMap>;
759

            
760
// Base class for both response headers and trailers.
761
class ResponseHeaderOrTrailerMap {
762
public:
763
366514
  virtual ~ResponseHeaderOrTrailerMap() = default;
764

            
765
  INLINE_RESP_STRING_HEADERS_TRAILERS(DEFINE_INLINE_STRING_HEADER)
766
  INLINE_RESP_NUMERIC_HEADERS_TRAILERS(DEFINE_INLINE_NUMERIC_HEADER)
767
};
768

            
769
// Response headers.
770
class ResponseHeaderMap
771
    : public RequestOrResponseHeaderMap,
772
      public ResponseHeaderOrTrailerMap,
773
      public CustomInlineHeaderBase<CustomInlineHeaderRegistry::Type::ResponseHeaders> {
774
public:
775
  INLINE_RESP_STRING_HEADERS(DEFINE_INLINE_STRING_HEADER)
776
  INLINE_RESP_NUMERIC_HEADERS(DEFINE_INLINE_NUMERIC_HEADER)
777
};
778
using ResponseHeaderMapPtr = std::unique_ptr<ResponseHeaderMap>;
779
using ResponseHeaderMapSharedPtr = std::shared_ptr<ResponseHeaderMap>;
780
using ResponseHeaderMapConstSharedPtr = std::shared_ptr<const ResponseHeaderMap>;
781
using ResponseHeaderMapOptRef = OptRef<ResponseHeaderMap>;
782
using ResponseHeaderMapOptConstRef = OptRef<const ResponseHeaderMap>;
783

            
784
// Response trailers.
785
class ResponseTrailerMap
786
    : public ResponseHeaderOrTrailerMap,
787
      public HeaderMap,
788
      public CustomInlineHeaderBase<CustomInlineHeaderRegistry::Type::ResponseTrailers> {};
789
using ResponseTrailerMapPtr = std::unique_ptr<ResponseTrailerMap>;
790
using ResponseTrailerMapSharedPtr = std::shared_ptr<ResponseTrailerMap>;
791
using ResponseTrailerMapConstSharedPtr = std::shared_ptr<const ResponseTrailerMap>;
792
using ResponseTrailerMapOptRef = OptRef<ResponseTrailerMap>;
793
using ResponseTrailerMapOptConstRef = OptRef<const ResponseTrailerMap>;
794

            
795
/**
796
 * Base class for both tunnel response headers and trailers.
797
 */
798
class TunnelResponseHeadersOrTrailers : public StreamInfo::FilterState::Object {
799
public:
800
  virtual const HeaderMap& value() const PURE;
801
};
802

            
803
/**
804
 * Convenient container type for storing Http::LowerCaseString and std::string key/value pairs.
805
 */
806
using HeaderVector = std::vector<std::pair<LowerCaseString, std::string>>;
807

            
808
/**
809
 * An interface to be implemented by header matchers.
810
 */
811
class HeaderMatcher {
812
public:
813
1953
  virtual ~HeaderMatcher() = default;
814

            
815
  /**
816
   * Check whether header matcher matches any headers in a given HeaderMap.
817
   */
818
  virtual bool matchesHeaders(const HeaderMap& headers) const PURE;
819

            
820
  /**
821
   * Matches headers validating each value individually.
822
   */
823
  virtual bool matchesHeadersIndividually(const HeaderMap& headers) const PURE;
824
};
825

            
826
using HeaderMatcherSharedPtr = std::shared_ptr<HeaderMatcher>;
827

            
828
} // namespace Http
829
} // namespace Envoy
830

            
831
// NOLINT(namespace-envoy)
832
namespace fmt {
833
// Allow fmtlib to use operator << defined in HeaderMap and LowerCaseString
834
template <> struct formatter<::Envoy::Http::LowerCaseString> : ostream_formatter {};
835

            
836
template <typename HeaderMapType>
837
struct formatter<
838
    HeaderMapType,
839
    std::enable_if_t<std::is_base_of<::Envoy::Http::HeaderMap, HeaderMapType>::value, char>>
840
    : ostream_formatter {};
841
} // namespace fmt