Coverage Report

Created: 2023-11-12 09:30

/proc/self/cwd/source/common/http/header_map_impl.cc
Line
Count
Source (jump to first uncovered line)
1
#include "source/common/http/header_map_impl.h"
2
3
#include <cstdint>
4
#include <list>
5
#include <memory>
6
#include <string>
7
8
#include "envoy/http/header_map.h"
9
10
#include "source/common/common/assert.h"
11
#include "source/common/common/dump_state_utils.h"
12
#include "source/common/common/empty_string.h"
13
#include "source/common/runtime/runtime_features.h"
14
#include "source/common/singleton/const_singleton.h"
15
16
#include "absl/strings/match.h"
17
18
namespace Envoy {
19
namespace Http {
20
21
bool HeaderStringValidator::disable_validation_for_tests_ = false;
22
23
namespace {
24
25
constexpr absl::string_view DelimiterForInlineHeaders{","};
26
constexpr absl::string_view DelimiterForInlineCookies{"; "};
27
const static int kMinHeadersForLazyMap = 3; // Optimal hard-coded value based on benchmarks.
28
29
0
bool validatedLowerCaseString(absl::string_view str) {
30
0
  auto lower_case_str = LowerCaseString(str);
31
0
  return lower_case_str == str;
32
0
}
33
34
295k
absl::string_view delimiterByHeader(const LowerCaseString& key) {
35
295k
  if (key == Http::Headers::get().Cookie) {
36
7.94k
    return DelimiterForInlineCookies;
37
7.94k
  }
38
287k
  return DelimiterForInlineHeaders;
39
295k
}
40
41
} // namespace
42
43
// Initialize as a Type::Reference
44
HeaderString::HeaderString(const LowerCaseString& ref_value) noexcept
45
3.56M
    : UnionStringBase(absl::string_view(ref_value.get().c_str(), ref_value.get().size())) {
46
3.56M
  ASSERT(valid());
47
3.56M
}
48
49
0
HeaderString::HeaderString(UnionString&& move_value) noexcept {
50
0
  buffer_ = std::move(move_value.storage());
51
0
  move_value.clear();
52
0
  ASSERT(valid());
53
0
}
54
55
// Specialization needed for HeaderMapImpl::HeaderList::insert() when key is LowerCaseString.
56
// A fully specialized template must be defined once in the program, hence this may not be in
57
// a header file.
58
3.09M
template <> bool HeaderMapImpl::HeaderList::isPseudoHeader(const LowerCaseString& key) {
59
3.09M
  return key.get().c_str()[0] == ':';
60
3.09M
}
61
62
546k
bool HeaderMapImpl::HeaderList::maybeMakeMap() {
63
546k
  if (lazy_map_.empty()) {
64
182k
    if (headers_.size() < kMinHeadersForLazyMap) {
65
85.7k
      return false;
66
85.7k
    }
67
    // Add all entries from the list into the map.
68
658k
    for (auto node = headers_.begin(); node != headers_.end(); ++node) {
69
561k
      HeaderNodeVector& v = lazy_map_[node->key().getStringView()];
70
561k
      v.push_back(node);
71
561k
    }
72
96.7k
  }
73
460k
  return true;
74
546k
}
75
76
161k
size_t HeaderMapImpl::HeaderList::remove(absl::string_view key) {
77
161k
  size_t removed_bytes = 0;
78
161k
  if (maybeMakeMap()) {
79
135k
    auto iter = lazy_map_.find(key);
80
135k
    if (iter != lazy_map_.end()) {
81
      // Erase from the map, and all same key entries from the list.
82
78.7k
      HeaderNodeVector header_nodes = std::move(iter->second);
83
78.7k
      lazy_map_.erase(iter);
84
98.4k
      for (const HeaderNode& node : header_nodes) {
85
98.4k
        ASSERT(node->key() == key);
86
98.4k
        removed_bytes += node->key().size() + node->value().size();
87
98.4k
        erase(node, false /* remove_from_map */);
88
98.4k
      }
89
78.7k
    }
90
135k
  } else {
91
    // Erase all same key entries from the list.
92
50.4k
    for (auto i = headers_.begin(); i != headers_.end();) {
93
23.9k
      if (i->key() == key) {
94
3.47k
        removed_bytes += i->key().size() + i->value().size();
95
3.47k
        i = erase(i, false /* remove_from_map */);
96
20.4k
      } else {
97
20.4k
        ++i;
98
20.4k
      }
99
23.9k
    }
100
26.4k
  }
101
161k
  return removed_bytes;
102
161k
}
103
104
1.09M
HeaderMapImpl::HeaderEntryImpl::HeaderEntryImpl(const LowerCaseString& key) : key_(key) {}
105
106
HeaderMapImpl::HeaderEntryImpl::HeaderEntryImpl(const LowerCaseString& key, HeaderString&& value)
107
1.99M
    : key_(key), value_(std::move(value)) {}
108
109
HeaderMapImpl::HeaderEntryImpl::HeaderEntryImpl(HeaderString&& key, HeaderString&& value)
110
1.57M
    : key_(std::move(key)), value_(std::move(value)) {}
111
112
0
void HeaderMapImpl::HeaderEntryImpl::value(absl::string_view value) { value_.setCopy(value); }
113
114
0
void HeaderMapImpl::HeaderEntryImpl::value(uint64_t value) { value_.setInteger(value); }
115
116
0
void HeaderMapImpl::HeaderEntryImpl::value(const HeaderEntry& header) {
117
0
  value(header.value().getStringView());
118
0
}
119
120
32
template <> HeaderMapImpl::StaticLookupTable<RequestHeaderMap>::StaticLookupTable() {
121
32
#define REGISTER_DEFAULT_REQUEST_HEADER(name)                                                      \
122
1.53k
  CustomInlineHeaderRegistry::registerInlineHeader<RequestHeaderMap::header_map_type>(             \
123
1.53k
      Headers::get().name);
124
1.15k
  INLINE_REQ_HEADERS(REGISTER_DEFAULT_REQUEST_HEADER)
125
384
  INLINE_REQ_RESP_HEADERS(REGISTER_DEFAULT_REQUEST_HEADER)
126
127
32
  finalizeTable();
128
129
  // Special case where we map a legacy host header to :authority.
130
32
  const auto handle =
131
32
      CustomInlineHeaderRegistry::getInlineHeader<RequestHeaderMap::header_map_type>(
132
32
          Headers::get().Host);
133
26.9k
  add(Headers::get().HostLegacy.get().c_str(), [handle](HeaderMapImpl& h) -> StaticLookupResponse {
134
26.9k
    return {&h.inlineHeaders()[handle.value().it_->second], &handle.value().it_->first};
135
26.9k
  });
136
32
}
137
138
22
template <> HeaderMapImpl::StaticLookupTable<RequestTrailerMap>::StaticLookupTable() {
139
22
  finalizeTable();
140
22
}
141
142
26
template <> HeaderMapImpl::StaticLookupTable<ResponseHeaderMap>::StaticLookupTable() {
143
26
#define REGISTER_RESPONSE_HEADER(name)                                                             \
144
624
  CustomInlineHeaderRegistry::registerInlineHeader<ResponseHeaderMap::header_map_type>(            \
145
624
      Headers::get().name);
146
260
  INLINE_RESP_HEADERS(REGISTER_RESPONSE_HEADER)
147
312
  INLINE_REQ_RESP_HEADERS(REGISTER_RESPONSE_HEADER)
148
52
  INLINE_RESP_HEADERS_TRAILERS(REGISTER_RESPONSE_HEADER)
149
150
26
  finalizeTable();
151
26
}
152
153
25
template <> HeaderMapImpl::StaticLookupTable<ResponseTrailerMap>::StaticLookupTable() {
154
25
#define REGISTER_RESPONSE_TRAILER(name)                                                            \
155
50
  CustomInlineHeaderRegistry::registerInlineHeader<ResponseTrailerMap::header_map_type>(           \
156
50
      Headers::get().name);
157
50
  INLINE_RESP_HEADERS_TRAILERS(REGISTER_RESPONSE_TRAILER)
158
159
25
  finalizeTable();
160
25
}
161
162
uint64_t HeaderMapImpl::appendToHeader(HeaderString& header, absl::string_view data,
163
360k
                                       absl::string_view delimiter) {
164
360k
  if (data.empty()) {
165
90.3k
    return 0;
166
90.3k
  }
167
269k
  uint64_t byte_size = 0;
168
269k
  if (!header.empty()) {
169
201k
    header.append(delimiter.data(), delimiter.size());
170
201k
    byte_size += delimiter.size();
171
201k
  }
172
269k
  header.append(data.data(), data.size());
173
269k
  return data.size() + byte_size;
174
360k
}
175
176
1.19M
void HeaderMapImpl::updateSize(uint64_t from_size, uint64_t to_size) {
177
1.19M
  ASSERT(cached_byte_size_ >= from_size);
178
1.19M
  cached_byte_size_ -= from_size;
179
1.19M
  cached_byte_size_ += to_size;
180
1.19M
}
181
182
5.05M
void HeaderMapImpl::addSize(uint64_t size) { cached_byte_size_ += size; }
183
184
249k
void HeaderMapImpl::subtractSize(uint64_t size) {
185
249k
  ASSERT(cached_byte_size_ >= size);
186
249k
  cached_byte_size_ -= size;
187
249k
}
188
189
346k
void HeaderMapImpl::copyFrom(HeaderMap& lhs, const HeaderMap& header_map) {
190
1.08M
  header_map.iterate([&lhs](const HeaderEntry& header) -> HeaderMap::Iterate {
191
    // TODO(mattklein123) PERF: Avoid copying here if not necessary.
192
1.08M
    HeaderString key_string;
193
1.08M
    key_string.setCopy(header.key().getStringView());
194
1.08M
    HeaderString value_string;
195
1.08M
    value_string.setCopy(header.value().getStringView());
196
197
1.08M
    lhs.addViaMove(std::move(key_string), std::move(value_string));
198
1.08M
    return HeaderMap::Iterate::Continue;
199
1.08M
  });
200
346k
}
201
202
namespace {
203
204
// This is currently only used in tests and is not optimized for performance.
205
HeaderMap::ConstIterateCb
206
0
collectAllHeaders(std::vector<std::pair<absl::string_view, absl::string_view>>* dest) {
207
0
  return [dest](const HeaderEntry& header) -> HeaderMap::Iterate {
208
0
    dest->push_back(std::make_pair(header.key().getStringView(), header.value().getStringView()));
209
0
    return HeaderMap::Iterate::Continue;
210
0
  };
211
0
};
212
213
} // namespace
214
215
// This is currently only used in tests and is not optimized for performance.
216
0
bool HeaderMapImpl::operator==(const HeaderMap& rhs) const {
217
0
  if (size() != rhs.size()) {
218
0
    return false;
219
0
  }
220
221
0
  std::vector<std::pair<absl::string_view, absl::string_view>> rhs_headers;
222
0
  rhs_headers.reserve(rhs.size());
223
0
  rhs.iterate(collectAllHeaders(&rhs_headers));
224
225
0
  auto i = headers_.begin();
226
0
  auto j = rhs_headers.begin();
227
0
  for (; i != headers_.end(); ++i, ++j) {
228
0
    if (i->key() != j->first || i->value() != j->second) {
229
0
      return false;
230
0
    }
231
0
  }
232
233
0
  return true;
234
0
}
235
236
0
bool HeaderMapImpl::operator!=(const HeaderMap& rhs) const { return !operator==(rhs); }
237
238
3.85M
void HeaderMapImpl::insertByKey(HeaderString&& key, HeaderString&& value) {
239
3.85M
  auto lookup = staticLookup(key.getStringView());
240
3.85M
  if (lookup.has_value()) {
241
2.28M
    key.clear();
242
2.28M
    if (*lookup.value().entry_ == nullptr) {
243
1.99M
      maybeCreateInline(lookup.value().entry_, *lookup.value().key_, std::move(value));
244
1.99M
    } else {
245
286k
      const auto delimiter = delimiterByHeader(*lookup.value().key_);
246
286k
      const uint64_t added_size =
247
286k
          appendToHeader((*lookup.value().entry_)->value(), value.getStringView(), delimiter);
248
286k
      addSize(added_size);
249
286k
      value.clear();
250
286k
    }
251
2.28M
  } else {
252
1.57M
    addSize(key.size() + value.size());
253
1.57M
    HeaderNode i = headers_.insert(std::move(key), std::move(value));
254
1.57M
    i->entry_ = i;
255
1.57M
  }
256
3.85M
}
257
258
2.06M
void HeaderMapImpl::addViaMove(HeaderString&& key, HeaderString&& value) {
259
2.06M
  insertByKey(std::move(key), std::move(value));
260
2.06M
}
261
262
10.9k
void HeaderMapImpl::addReference(const LowerCaseString& key, absl::string_view value) {
263
10.9k
  HeaderString ref_key(key);
264
10.9k
  HeaderString ref_value(value);
265
10.9k
  insertByKey(std::move(ref_key), std::move(ref_value));
266
10.9k
}
267
268
72
void HeaderMapImpl::addReferenceKey(const LowerCaseString& key, uint64_t value) {
269
72
  HeaderString ref_key(key);
270
72
  HeaderString new_value;
271
72
  new_value.setInteger(value);
272
72
  insertByKey(std::move(ref_key), std::move(new_value));
273
72
  ASSERT(new_value.empty()); // NOLINT(bugprone-use-after-move)
274
72
}
275
276
441k
void HeaderMapImpl::addReferenceKey(const LowerCaseString& key, absl::string_view value) {
277
441k
  HeaderString ref_key(key);
278
441k
  HeaderString new_value;
279
441k
  new_value.setCopy(value);
280
441k
  insertByKey(std::move(ref_key), std::move(new_value));
281
441k
  ASSERT(new_value.empty()); // NOLINT(bugprone-use-after-move)
282
441k
}
283
284
609
void HeaderMapImpl::addCopy(const LowerCaseString& key, uint64_t value) {
285
  // In the case that the header is appended, we will perform a needless copy of the key and value.
286
  // This is done on purpose to keep the code simple and should be rare.
287
609
  HeaderString new_key;
288
609
  new_key.setCopy(key.get());
289
609
  HeaderString new_value;
290
609
  new_value.setInteger(value);
291
609
  insertByKey(std::move(new_key), std::move(new_value));
292
609
  ASSERT(new_key.empty());   // NOLINT(bugprone-use-after-move)
293
609
  ASSERT(new_value.empty()); // NOLINT(bugprone-use-after-move)
294
609
}
295
296
1.33M
void HeaderMapImpl::addCopy(const LowerCaseString& key, absl::string_view value) {
297
  // In the case that the header is appended, we will perform a needless copy of the key and value.
298
  // This is done on purpose to keep the code simple and should be rare.
299
1.33M
  HeaderString new_key;
300
1.33M
  new_key.setCopy(key.get());
301
1.33M
  HeaderString new_value;
302
1.33M
  new_value.setCopy(value);
303
1.33M
  insertByKey(std::move(new_key), std::move(new_value));
304
1.33M
  ASSERT(new_key.empty());   // NOLINT(bugprone-use-after-move)
305
1.33M
  ASSERT(new_value.empty()); // NOLINT(bugprone-use-after-move)
306
1.33M
}
307
308
17.8k
void HeaderMapImpl::appendCopy(const LowerCaseString& key, absl::string_view value) {
309
  // TODO(#9221): converge on and document a policy for coalescing multiple headers.
310
17.8k
  auto entry = getExisting(key);
311
17.8k
  if (!entry.empty()) {
312
8.90k
    const auto delimiter = delimiterByHeader(key);
313
8.90k
    const uint64_t added_size = appendToHeader(entry[0]->value(), value, delimiter);
314
8.90k
    addSize(added_size);
315
8.96k
  } else {
316
8.96k
    addCopy(key, value);
317
8.96k
  }
318
17.8k
}
319
320
4.20k
void HeaderMapImpl::setReference(const LowerCaseString& key, absl::string_view value) {
321
4.20k
  remove(key);
322
4.20k
  addReference(key, value);
323
4.20k
}
324
325
238k
void HeaderMapImpl::setReferenceKey(const LowerCaseString& key, absl::string_view value) {
326
238k
  remove(key);
327
238k
  addReferenceKey(key, value);
328
238k
}
329
330
32.0k
void HeaderMapImpl::setCopy(const LowerCaseString& key, absl::string_view value) {
331
32.0k
  remove(key);
332
32.0k
  addCopy(key, value);
333
32.0k
}
334
335
1.81M
uint64_t HeaderMapImpl::byteSize() const { return cached_byte_size_; }
336
337
4.17M
void HeaderMapImpl::verifyByteSizeInternalForTest() const {
338
  // Computes the total byte size by summing the byte size of the keys and values.
339
4.17M
  uint64_t byte_size = 0;
340
189M
  for (const HeaderEntryImpl& header : headers_) {
341
189M
    byte_size += header.key().size();
342
189M
    byte_size += header.value().size();
343
189M
  }
344
4.17M
  ASSERT(cached_byte_size_ == byte_size);
345
4.17M
}
346
347
419k
HeaderMap::GetResult HeaderMapImpl::get(const LowerCaseString& key) const {
348
419k
  return HeaderMap::GetResult(const_cast<HeaderMapImpl*>(this)->getExisting(key));
349
419k
}
350
351
437k
HeaderMap::NonConstGetResult HeaderMapImpl::getExisting(absl::string_view key) {
352
  // Attempt a trie lookup first to see if the user is requesting an O(1) header. This may be
353
  // relatively common in certain header matching / routing patterns.
354
  // TODO(mattklein123): Add inline handle support directly to the header matcher code to support
355
  // this use case more directly.
356
437k
  HeaderMap::NonConstGetResult ret;
357
437k
  auto lookup = staticLookup(key);
358
437k
  if (lookup.has_value()) {
359
53.1k
    if (*lookup.value().entry_ != nullptr) {
360
30.1k
      ret.push_back(*lookup.value().entry_);
361
30.1k
    }
362
53.1k
    return ret;
363
53.1k
  }
364
365
  // If the requested header is not an O(1) header try using the lazy map to
366
  // search for it instead of iterating the headers list.
367
384k
  if (headers_.maybeMakeMap()) {
368
325k
    HeaderList::HeaderLazyMap::iterator iter = headers_.mapFind(key);
369
325k
    if (iter != headers_.mapEnd()) {
370
232k
      const HeaderList::HeaderNodeVector& v = iter->second;
371
232k
      ASSERT(!v.empty()); // It's impossible to have a map entry with an empty vector as its value.
372
441k
      for (const auto& values_it : v) {
373
        // Convert the iterated value to a HeaderEntry*.
374
441k
        ret.push_back(&(*values_it));
375
441k
      }
376
232k
    }
377
325k
    return ret;
378
325k
  }
379
380
  // If the requested header is not an O(1) header and the lazy map is not in use, we do a full
381
  // scan. Doing the trie lookup is wasteful in the miss case, but is present for code consistency
382
  // with other functions that do similar things.
383
59.3k
  for (HeaderEntryImpl& header : headers_) {
384
43.5k
    if (header.key() == key) {
385
11.5k
      ret.push_back(&header);
386
11.5k
    }
387
43.5k
  }
388
389
59.3k
  return ret;
390
384k
}
391
392
643k
void HeaderMapImpl::iterate(HeaderMap::ConstIterateCb cb) const {
393
3.15M
  for (const HeaderEntryImpl& header : headers_) {
394
3.15M
    if (cb(header) == HeaderMap::Iterate::Break) {
395
13.9k
      break;
396
13.9k
    }
397
3.15M
  }
398
643k
}
399
400
27.5k
void HeaderMapImpl::iterateReverse(HeaderMap::ConstIterateCb cb) const {
401
392k
  for (auto it = headers_.rbegin(); it != headers_.rend(); it++) {
402
364k
    if (cb(*it) == HeaderMap::Iterate::Break) {
403
0
      break;
404
0
    }
405
364k
  }
406
27.5k
}
407
408
290k
void HeaderMapImpl::clear() {
409
290k
  clearInline();
410
290k
  headers_.clear();
411
290k
  cached_byte_size_ = 0;
412
290k
}
413
414
1.61k
size_t HeaderMapImpl::removeIf(const HeaderMap::HeaderMatchPredicate& predicate) {
415
1.61k
  const size_t old_size = headers_.size();
416
10.1k
  headers_.removeIf([&predicate, this](const HeaderEntryImpl& entry) {
417
10.1k
    const bool to_remove = predicate(entry);
418
10.1k
    if (to_remove) {
419
      // If this header should be removed, make sure any references in the
420
      // static lookup table are cleared as well.
421
3.70k
      auto lookup = staticLookup(entry.key().getStringView());
422
3.70k
      if (lookup.has_value()) {
423
75
        if (lookup.value().entry_) {
424
75
          const uint32_t key_value_size =
425
75
              (*lookup.value().entry_)->key().size() + (*lookup.value().entry_)->value().size();
426
75
          subtractSize(key_value_size);
427
75
          *lookup.value().entry_ = nullptr;
428
75
        }
429
3.63k
      } else {
430
3.63k
        subtractSize(entry.key().size() + entry.value().size());
431
3.63k
      }
432
3.70k
    }
433
10.1k
    return to_remove;
434
10.1k
  });
435
1.61k
  return old_size - headers_.size();
436
1.61k
}
437
438
365k
size_t HeaderMapImpl::remove(const LowerCaseString& key) { return removeExisting(key); }
439
440
1.61k
size_t HeaderMapImpl::removePrefix(const LowerCaseString& prefix) {
441
10.1k
  return HeaderMapImpl::removeIf([&prefix](const HeaderEntry& entry) -> bool {
442
10.1k
    return absl::StartsWith(entry.key().getStringView(), prefix.get());
443
10.1k
  });
444
1.61k
}
445
446
0
void HeaderMapImpl::dumpState(std::ostream& os, int indent_level) const {
447
0
  iterate([&os,
448
0
           spaces = spacesForLevel(indent_level)](const HeaderEntry& header) -> HeaderMap::Iterate {
449
0
    os << spaces << "'" << header.key().getStringView() << "', '" << header.value().getStringView()
450
0
       << "'\n";
451
0
    return HeaderMap::Iterate::Continue;
452
0
  });
453
0
}
454
455
HeaderMapImpl::HeaderEntryImpl& HeaderMapImpl::maybeCreateInline(HeaderEntryImpl** entry,
456
1.29M
                                                                 const LowerCaseString& key) {
457
1.29M
  if (*entry) {
458
198k
    return **entry;
459
198k
  }
460
461
1.09M
  addSize(key.get().size());
462
1.09M
  HeaderNode i = headers_.insert(key);
463
1.09M
  i->entry_ = i;
464
1.09M
  *entry = &(*i);
465
1.09M
  return **entry;
466
1.29M
}
467
468
HeaderMapImpl::HeaderEntryImpl& HeaderMapImpl::maybeCreateInline(HeaderEntryImpl** entry,
469
                                                                 const LowerCaseString& key,
470
1.99M
                                                                 HeaderString&& value) {
471
1.99M
  if (*entry) {
472
0
    value.clear();
473
0
    return **entry;
474
0
  }
475
476
1.99M
  addSize(key.get().size() + value.size());
477
1.99M
  HeaderNode i = headers_.insert(key, std::move(value));
478
1.99M
  i->entry_ = i;
479
1.99M
  *entry = &(*i);
480
1.99M
  return **entry;
481
1.99M
}
482
483
365k
size_t HeaderMapImpl::removeExisting(absl::string_view key) {
484
365k
  const size_t old_size = headers_.size();
485
365k
  auto lookup = staticLookup(key);
486
365k
  if (lookup.has_value()) {
487
203k
    removeInline(lookup.value().entry_);
488
203k
  } else {
489
161k
    subtractSize(headers_.remove(key));
490
161k
  }
491
365k
  return old_size - headers_.size();
492
365k
}
493
494
2.68M
size_t HeaderMapImpl::removeInline(HeaderEntryImpl** ptr_to_entry) {
495
2.68M
  if (!*ptr_to_entry) {
496
2.63M
    return 0;
497
2.63M
  }
498
499
48.0k
  HeaderEntryImpl* entry = *ptr_to_entry;
500
48.0k
  const uint64_t size_to_subtract = entry->entry_->key().size() + entry->entry_->value().size();
501
48.0k
  subtractSize(size_to_subtract);
502
48.0k
  *ptr_to_entry = nullptr;
503
48.0k
  headers_.erase(entry->entry_, true);
504
48.0k
  return 1;
505
2.68M
}
506
507
namespace {
508
template <class T>
509
21.9k
HeaderMapImplUtility::HeaderMapImplInfo makeHeaderMapImplInfo(absl::string_view name) {
510
  // Constructing a header map implementation will force the custom headers and sizing to be
511
  // finalized, so do that first.
512
21.9k
  auto header_map = T::create();
513
514
21.9k
  HeaderMapImplUtility::HeaderMapImplInfo info;
515
21.9k
  info.name_ = std::string(name);
516
21.9k
  info.size_ = T::inlineHeadersSize() + sizeof(T);
517
502k
  for (const auto& header : CustomInlineHeaderRegistry::headers<T::header_map_type>()) {
518
502k
    info.registered_headers_.push_back(header.first.get());
519
502k
  }
520
21.9k
  return info;
521
21.9k
}
header_map_impl.cc:Envoy::Http::HeaderMapImplUtility::HeaderMapImplInfo Envoy::Http::(anonymous namespace)::makeHeaderMapImplInfo<Envoy::Http::RequestHeaderMapImpl>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
509
5.48k
HeaderMapImplUtility::HeaderMapImplInfo makeHeaderMapImplInfo(absl::string_view name) {
510
  // Constructing a header map implementation will force the custom headers and sizing to be
511
  // finalized, so do that first.
512
5.48k
  auto header_map = T::create();
513
514
5.48k
  HeaderMapImplUtility::HeaderMapImplInfo info;
515
5.48k
  info.name_ = std::string(name);
516
5.48k
  info.size_ = T::inlineHeadersSize() + sizeof(T);
517
320k
  for (const auto& header : CustomInlineHeaderRegistry::headers<T::header_map_type>()) {
518
320k
    info.registered_headers_.push_back(header.first.get());
519
320k
  }
520
5.48k
  return info;
521
5.48k
}
header_map_impl.cc:Envoy::Http::HeaderMapImplUtility::HeaderMapImplInfo Envoy::Http::(anonymous namespace)::makeHeaderMapImplInfo<Envoy::Http::RequestTrailerMapImpl>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
509
5.48k
HeaderMapImplUtility::HeaderMapImplInfo makeHeaderMapImplInfo(absl::string_view name) {
510
  // Constructing a header map implementation will force the custom headers and sizing to be
511
  // finalized, so do that first.
512
5.48k
  auto header_map = T::create();
513
514
5.48k
  HeaderMapImplUtility::HeaderMapImplInfo info;
515
5.48k
  info.name_ = std::string(name);
516
5.48k
  info.size_ = T::inlineHeadersSize() + sizeof(T);
517
5.48k
  for (const auto& header : CustomInlineHeaderRegistry::headers<T::header_map_type>()) {
518
0
    info.registered_headers_.push_back(header.first.get());
519
0
  }
520
5.48k
  return info;
521
5.48k
}
header_map_impl.cc:Envoy::Http::HeaderMapImplUtility::HeaderMapImplInfo Envoy::Http::(anonymous namespace)::makeHeaderMapImplInfo<Envoy::Http::ResponseHeaderMapImpl>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
509
5.48k
HeaderMapImplUtility::HeaderMapImplInfo makeHeaderMapImplInfo(absl::string_view name) {
510
  // Constructing a header map implementation will force the custom headers and sizing to be
511
  // finalized, so do that first.
512
5.48k
  auto header_map = T::create();
513
514
5.48k
  HeaderMapImplUtility::HeaderMapImplInfo info;
515
5.48k
  info.name_ = std::string(name);
516
5.48k
  info.size_ = T::inlineHeadersSize() + sizeof(T);
517
171k
  for (const auto& header : CustomInlineHeaderRegistry::headers<T::header_map_type>()) {
518
171k
    info.registered_headers_.push_back(header.first.get());
519
171k
  }
520
5.48k
  return info;
521
5.48k
}
header_map_impl.cc:Envoy::Http::HeaderMapImplUtility::HeaderMapImplInfo Envoy::Http::(anonymous namespace)::makeHeaderMapImplInfo<Envoy::Http::ResponseTrailerMapImpl>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
509
5.48k
HeaderMapImplUtility::HeaderMapImplInfo makeHeaderMapImplInfo(absl::string_view name) {
510
  // Constructing a header map implementation will force the custom headers and sizing to be
511
  // finalized, so do that first.
512
5.48k
  auto header_map = T::create();
513
514
5.48k
  HeaderMapImplUtility::HeaderMapImplInfo info;
515
5.48k
  info.name_ = std::string(name);
516
5.48k
  info.size_ = T::inlineHeadersSize() + sizeof(T);
517
10.9k
  for (const auto& header : CustomInlineHeaderRegistry::headers<T::header_map_type>()) {
518
10.9k
    info.registered_headers_.push_back(header.first.get());
519
10.9k
  }
520
5.48k
  return info;
521
5.48k
}
522
} // namespace
523
524
std::vector<HeaderMapImplUtility::HeaderMapImplInfo>
525
5.48k
HeaderMapImplUtility::getAllHeaderMapImplInfo() {
526
5.48k
  std::vector<HeaderMapImplUtility::HeaderMapImplInfo> ret;
527
5.48k
  ret.push_back(makeHeaderMapImplInfo<RequestHeaderMapImpl>("request header map"));
528
5.48k
  ret.push_back(makeHeaderMapImplInfo<RequestTrailerMapImpl>("request trailer map"));
529
5.48k
  ret.push_back(makeHeaderMapImplInfo<ResponseHeaderMapImpl>("response header map"));
530
5.48k
  ret.push_back(makeHeaderMapImplInfo<ResponseTrailerMapImpl>("response trailer map"));
531
5.48k
  return ret;
532
5.48k
}
533
534
0
absl::string_view RequestHeaderMapImpl::protocol() const { return getProtocolValue(); }
535
536
0
absl::string_view RequestHeaderMapImpl::host() const { return getHostValue(); }
537
538
2.97k
absl::string_view RequestHeaderMapImpl::path() const { return getPathValue(); }
539
540
1.11k
absl::string_view RequestHeaderMapImpl::method() const { return getMethodValue(); }
541
542
0
void RequestHeaderMapImpl::forEach(Tracing::TraceContext::IterateCallback callback) const {
543
0
  HeaderMapImpl::iterate([cb = std::move(callback)](const HeaderEntry& entry) {
544
0
    if (cb(entry.key().getStringView(), entry.value().getStringView())) {
545
0
      return HeaderMap::Iterate::Continue;
546
0
    }
547
0
    return HeaderMap::Iterate::Break;
548
0
  });
549
0
}
550
551
0
absl::optional<absl::string_view> RequestHeaderMapImpl::getByKey(absl::string_view key) const {
552
0
  ASSERT(validatedLowerCaseString(key));
553
0
  auto result = const_cast<RequestHeaderMapImpl*>(this)->getExisting(key);
554
555
0
  if (result.empty()) {
556
0
    return absl::nullopt;
557
0
  }
558
0
  return result[0]->value().getStringView();
559
0
}
560
561
0
void RequestHeaderMapImpl::setByKey(absl::string_view key, absl::string_view val) {
562
0
  ASSERT(validatedLowerCaseString(key));
563
0
  HeaderMapImpl::removeExisting(key);
564
565
0
  HeaderString new_key;
566
0
  new_key.setCopy(key);
567
0
  HeaderString new_val;
568
0
  new_val.setCopy(val);
569
570
0
  HeaderMapImpl::insertByKey(std::move(new_key), std::move(new_val));
571
0
}
572
573
0
void RequestHeaderMapImpl::setByReferenceKey(absl::string_view key, absl::string_view val) {
574
0
  ASSERT(validatedLowerCaseString(key));
575
0
  HeaderMapImpl::removeExisting(key);
576
577
0
  HeaderString new_val;
578
0
  new_val.setCopy(val);
579
580
0
  HeaderMapImpl::insertByKey(HeaderString(key), std::move(new_val));
581
0
}
582
583
0
void RequestHeaderMapImpl::setByReference(absl::string_view key, absl::string_view val) {
584
0
  ASSERT(validatedLowerCaseString(key));
585
0
  HeaderMapImpl::removeExisting(key);
586
587
0
  HeaderMapImpl::insertByKey(HeaderString(key), HeaderString(val));
588
0
}
589
590
0
void RequestHeaderMapImpl::removeByKey(absl::string_view key) {
591
0
  ASSERT(validatedLowerCaseString(key));
592
0
  HeaderMapImpl::removeExisting(key);
593
0
}
594
595
} // namespace Http
596
} // namespace Envoy