LCOV - code coverage report
Current view: top level - source/common/http - header_map_impl.cc (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 336 384 87.5 %
Date: 2024-01-05 06:35:25 Functions: 51 61 83.6 %

          Line data    Source code
       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        1385 : absl::string_view delimiterByHeader(const LowerCaseString& key) {
      30        1385 :   if (key == Http::Headers::get().Cookie) {
      31           0 :     return DelimiterForInlineCookies;
      32           0 :   }
      33        1385 :   return DelimiterForInlineHeaders;
      34        1385 : }
      35             : 
      36             : } // namespace
      37             : 
      38             : // Initialize as a Type::Reference
      39             : HeaderString::HeaderString(const LowerCaseString& ref_value) noexcept
      40       19455 :     : UnionStringBase(absl::string_view(ref_value.get().c_str(), ref_value.get().size())) {
      41       19455 :   ASSERT(valid());
      42       19455 : }
      43             : 
      44           0 : HeaderString::HeaderString(UnionString&& move_value) noexcept {
      45           0 :   buffer_ = std::move(move_value.storage());
      46           0 :   move_value.clear();
      47           0 :   ASSERT(valid());
      48           0 : }
      49             : 
      50             : // Specialization needed for HeaderMapImpl::HeaderList::insert() when key is LowerCaseString.
      51             : // A fully specialized template must be defined once in the program, hence this may not be in
      52             : // a header file.
      53       17569 : template <> bool HeaderMapImpl::HeaderList::isPseudoHeader(const LowerCaseString& key) {
      54       17569 :   return key.get().c_str()[0] == ':';
      55       17569 : }
      56             : 
      57        2633 : bool HeaderMapImpl::HeaderList::maybeMakeMap() {
      58        2633 :   if (lazy_map_.empty()) {
      59        2174 :     if (headers_.size() < kMinHeadersForLazyMap) {
      60        1370 :       return false;
      61        1370 :     }
      62             :     // Add all entries from the list into the map.
      63       70166 :     for (auto node = headers_.begin(); node != headers_.end(); ++node) {
      64       69362 :       HeaderNodeVector& v = lazy_map_[node->key().getStringView()];
      65       69362 :       v.push_back(node);
      66       69362 :     }
      67         804 :   }
      68        1263 :   return true;
      69        2633 : }
      70             : 
      71         660 : size_t HeaderMapImpl::HeaderList::remove(absl::string_view key) {
      72         660 :   size_t removed_bytes = 0;
      73         660 :   if (maybeMakeMap()) {
      74         156 :     auto iter = lazy_map_.find(key);
      75         156 :     if (iter != lazy_map_.end()) {
      76             :       // Erase from the map, and all same key entries from the list.
      77          76 :       HeaderNodeVector header_nodes = std::move(iter->second);
      78          76 :       lazy_map_.erase(iter);
      79         113 :       for (const HeaderNode& node : header_nodes) {
      80         113 :         ASSERT(node->key() == key);
      81         113 :         removed_bytes += node->key().size() + node->value().size();
      82         113 :         erase(node, false /* remove_from_map */);
      83         113 :       }
      84          76 :     }
      85         544 :   } else {
      86             :     // Erase all same key entries from the list.
      87        1051 :     for (auto i = headers_.begin(); i != headers_.end();) {
      88         547 :       if (i->key() == key) {
      89         128 :         removed_bytes += i->key().size() + i->value().size();
      90         128 :         i = erase(i, false /* remove_from_map */);
      91         420 :       } else {
      92         419 :         ++i;
      93         419 :       }
      94         547 :     }
      95         504 :   }
      96         660 :   return removed_bytes;
      97         660 : }
      98             : 
      99        7590 : HeaderMapImpl::HeaderEntryImpl::HeaderEntryImpl(const LowerCaseString& key) : key_(key) {}
     100             : 
     101             : HeaderMapImpl::HeaderEntryImpl::HeaderEntryImpl(const LowerCaseString& key, HeaderString&& value)
     102        9979 :     : key_(key), value_(std::move(value)) {}
     103             : 
     104             : HeaderMapImpl::HeaderEntryImpl::HeaderEntryImpl(HeaderString&& key, HeaderString&& value)
     105       73632 :     : key_(std::move(key)), value_(std::move(value)) {}
     106             : 
     107           0 : void HeaderMapImpl::HeaderEntryImpl::value(absl::string_view value) { value_.setCopy(value); }
     108             : 
     109           0 : void HeaderMapImpl::HeaderEntryImpl::value(uint64_t value) { value_.setInteger(value); }
     110             : 
     111           0 : void HeaderMapImpl::HeaderEntryImpl::value(const HeaderEntry& header) {
     112           0 :   value(header.value().getStringView());
     113           0 : }
     114             : 
     115          33 : template <> HeaderMapImpl::StaticLookupTable<RequestHeaderMap>::StaticLookupTable() {
     116          33 : #define REGISTER_DEFAULT_REQUEST_HEADER(name)                                                      \
     117        1584 :   CustomInlineHeaderRegistry::registerInlineHeader<RequestHeaderMap::header_map_type>(             \
     118        1584 :       Headers::get().name);
     119        1188 :   INLINE_REQ_HEADERS(REGISTER_DEFAULT_REQUEST_HEADER)
     120         396 :   INLINE_REQ_RESP_HEADERS(REGISTER_DEFAULT_REQUEST_HEADER)
     121             : 
     122          33 :   finalizeTable();
     123             : 
     124             :   // Special case where we map a legacy host header to :authority.
     125          33 :   const auto handle =
     126          33 :       CustomInlineHeaderRegistry::getInlineHeader<RequestHeaderMap::header_map_type>(
     127          33 :           Headers::get().Host);
     128         355 :   add(Headers::get().HostLegacy.get().c_str(), [handle](HeaderMapImpl& h) -> StaticLookupResponse {
     129         335 :     return {&h.inlineHeaders()[handle.value().it_->second], &handle.value().it_->first};
     130         335 :   });
     131          33 : }
     132             : 
     133          19 : template <> HeaderMapImpl::StaticLookupTable<RequestTrailerMap>::StaticLookupTable() {
     134          19 :   finalizeTable();
     135          19 : }
     136             : 
     137          26 : template <> HeaderMapImpl::StaticLookupTable<ResponseHeaderMap>::StaticLookupTable() {
     138          26 : #define REGISTER_RESPONSE_HEADER(name)                                                             \
     139         624 :   CustomInlineHeaderRegistry::registerInlineHeader<ResponseHeaderMap::header_map_type>(            \
     140         624 :       Headers::get().name);
     141         260 :   INLINE_RESP_HEADERS(REGISTER_RESPONSE_HEADER)
     142         312 :   INLINE_REQ_RESP_HEADERS(REGISTER_RESPONSE_HEADER)
     143          52 :   INLINE_RESP_HEADERS_TRAILERS(REGISTER_RESPONSE_HEADER)
     144             : 
     145          26 :   finalizeTable();
     146          26 : }
     147             : 
     148          23 : template <> HeaderMapImpl::StaticLookupTable<ResponseTrailerMap>::StaticLookupTable() {
     149          23 : #define REGISTER_RESPONSE_TRAILER(name)                                                            \
     150          46 :   CustomInlineHeaderRegistry::registerInlineHeader<ResponseTrailerMap::header_map_type>(           \
     151          46 :       Headers::get().name);
     152          46 :   INLINE_RESP_HEADERS_TRAILERS(REGISTER_RESPONSE_TRAILER)
     153             : 
     154          23 :   finalizeTable();
     155          23 : }
     156             : 
     157             : uint64_t HeaderMapImpl::appendToHeader(HeaderString& header, absl::string_view data,
     158        1574 :                                        absl::string_view delimiter) {
     159        1574 :   if (data.empty()) {
     160         952 :     return 0;
     161         952 :   }
     162         622 :   uint64_t byte_size = 0;
     163         622 :   if (!header.empty()) {
     164         422 :     header.append(delimiter.data(), delimiter.size());
     165         422 :     byte_size += delimiter.size();
     166         422 :   }
     167         622 :   header.append(data.data(), data.size());
     168         622 :   return data.size() + byte_size;
     169        1574 : }
     170             : 
     171        7908 : void HeaderMapImpl::updateSize(uint64_t from_size, uint64_t to_size) {
     172        7908 :   ASSERT(cached_byte_size_ >= from_size);
     173        7908 :   cached_byte_size_ -= from_size;
     174        7908 :   cached_byte_size_ += to_size;
     175        7908 : }
     176             : 
     177       93592 : void HeaderMapImpl::addSize(uint64_t size) { cached_byte_size_ += size; }
     178             : 
     179        1762 : void HeaderMapImpl::subtractSize(uint64_t size) {
     180        1762 :   ASSERT(cached_byte_size_ >= size);
     181        1762 :   cached_byte_size_ -= size;
     182        1762 : }
     183             : 
     184        1150 : void HeaderMapImpl::copyFrom(HeaderMap& lhs, const HeaderMap& header_map) {
     185        3756 :   header_map.iterate([&lhs](const HeaderEntry& header) -> HeaderMap::Iterate {
     186             :     // TODO(mattklein123) PERF: Avoid copying here if not necessary.
     187        3626 :     HeaderString key_string;
     188        3626 :     key_string.setCopy(header.key().getStringView());
     189        3626 :     HeaderString value_string;
     190        3626 :     value_string.setCopy(header.value().getStringView());
     191             : 
     192        3626 :     lhs.addViaMove(std::move(key_string), std::move(value_string));
     193        3626 :     return HeaderMap::Iterate::Continue;
     194        3626 :   });
     195        1150 : }
     196             : 
     197             : namespace {
     198             : 
     199             : // This is currently only used in tests and is not optimized for performance.
     200             : HeaderMap::ConstIterateCb
     201           0 : collectAllHeaders(std::vector<std::pair<absl::string_view, absl::string_view>>* dest) {
     202           0 :   return [dest](const HeaderEntry& header) -> HeaderMap::Iterate {
     203           0 :     dest->push_back(std::make_pair(header.key().getStringView(), header.value().getStringView()));
     204           0 :     return HeaderMap::Iterate::Continue;
     205           0 :   };
     206           0 : };
     207             : 
     208             : } // namespace
     209             : 
     210             : // This is currently only used in tests and is not optimized for performance.
     211           0 : bool HeaderMapImpl::operator==(const HeaderMap& rhs) const {
     212           0 :   if (size() != rhs.size()) {
     213           0 :     return false;
     214           0 :   }
     215             : 
     216           0 :   std::vector<std::pair<absl::string_view, absl::string_view>> rhs_headers;
     217           0 :   rhs_headers.reserve(rhs.size());
     218           0 :   rhs.iterate(collectAllHeaders(&rhs_headers));
     219             : 
     220           0 :   auto i = headers_.begin();
     221           0 :   auto j = rhs_headers.begin();
     222           0 :   for (; i != headers_.end(); ++i, ++j) {
     223           0 :     if (i->key() != j->first || i->value() != j->second) {
     224           0 :       return false;
     225           0 :     }
     226           0 :   }
     227             : 
     228           0 :   return true;
     229           0 : }
     230             : 
     231           0 : bool HeaderMapImpl::operator!=(const HeaderMap& rhs) const { return !operator==(rhs); }
     232             : 
     233       84965 : void HeaderMapImpl::insertByKey(HeaderString&& key, HeaderString&& value) {
     234       84965 :   auto lookup = staticLookup(key.getStringView());
     235       84965 :   if (lookup.has_value()) {
     236       11333 :     key.clear();
     237       11333 :     if (*lookup.value().entry_ == nullptr) {
     238        9979 :       maybeCreateInline(lookup.value().entry_, *lookup.value().key_, std::move(value));
     239       10868 :     } else {
     240        1354 :       const auto delimiter = delimiterByHeader(*lookup.value().key_);
     241        1354 :       const uint64_t added_size =
     242        1354 :           appendToHeader((*lookup.value().entry_)->value(), value.getStringView(), delimiter);
     243        1354 :       addSize(added_size);
     244        1354 :       value.clear();
     245        1354 :     }
     246       80284 :   } else {
     247       73632 :     addSize(key.size() + value.size());
     248       73632 :     HeaderNode i = headers_.insert(std::move(key), std::move(value));
     249       73632 :     i->entry_ = i;
     250       73632 :   }
     251       84965 : }
     252             : 
     253       13308 : void HeaderMapImpl::addViaMove(HeaderString&& key, HeaderString&& value) {
     254       13308 :   insertByKey(std::move(key), std::move(value));
     255       13308 : }
     256             : 
     257         810 : void HeaderMapImpl::addReference(const LowerCaseString& key, absl::string_view value) {
     258         810 :   HeaderString ref_key(key);
     259         810 :   HeaderString ref_value(value);
     260         810 :   insertByKey(std::move(ref_key), std::move(ref_value));
     261         810 : }
     262             : 
     263          48 : void HeaderMapImpl::addReferenceKey(const LowerCaseString& key, uint64_t value) {
     264          48 :   HeaderString ref_key(key);
     265          48 :   HeaderString new_value;
     266          48 :   new_value.setInteger(value);
     267          48 :   insertByKey(std::move(ref_key), std::move(new_value));
     268          48 :   ASSERT(new_value.empty()); // NOLINT(bugprone-use-after-move)
     269          48 : }
     270             : 
     271         574 : void HeaderMapImpl::addReferenceKey(const LowerCaseString& key, absl::string_view value) {
     272         574 :   HeaderString ref_key(key);
     273         574 :   HeaderString new_value;
     274         574 :   new_value.setCopy(value);
     275         574 :   insertByKey(std::move(ref_key), std::move(new_value));
     276         574 :   ASSERT(new_value.empty()); // NOLINT(bugprone-use-after-move)
     277         574 : }
     278             : 
     279          33 : void HeaderMapImpl::addCopy(const LowerCaseString& key, uint64_t value) {
     280             :   // In the case that the header is appended, we will perform a needless copy of the key and value.
     281             :   // This is done on purpose to keep the code simple and should be rare.
     282          33 :   HeaderString new_key;
     283          33 :   new_key.setCopy(key.get());
     284          33 :   HeaderString new_value;
     285          33 :   new_value.setInteger(value);
     286          33 :   insertByKey(std::move(new_key), std::move(new_value));
     287          33 :   ASSERT(new_key.empty());   // NOLINT(bugprone-use-after-move)
     288          33 :   ASSERT(new_value.empty()); // NOLINT(bugprone-use-after-move)
     289          33 : }
     290             : 
     291       70192 : void HeaderMapImpl::addCopy(const LowerCaseString& key, absl::string_view value) {
     292             :   // In the case that the header is appended, we will perform a needless copy of the key and value.
     293             :   // This is done on purpose to keep the code simple and should be rare.
     294       70192 :   HeaderString new_key;
     295       70192 :   new_key.setCopy(key.get());
     296       70192 :   HeaderString new_value;
     297       70192 :   new_value.setCopy(value);
     298       70192 :   insertByKey(std::move(new_key), std::move(new_value));
     299       70192 :   ASSERT(new_key.empty());   // NOLINT(bugprone-use-after-move)
     300       70192 :   ASSERT(new_value.empty()); // NOLINT(bugprone-use-after-move)
     301       70192 : }
     302             : 
     303         103 : void HeaderMapImpl::appendCopy(const LowerCaseString& key, absl::string_view value) {
     304             :   // TODO(#9221): converge on and document a policy for coalescing multiple headers.
     305         103 :   auto entry = getExisting(key);
     306         103 :   if (!entry.empty()) {
     307          31 :     const auto delimiter = delimiterByHeader(key);
     308          31 :     const uint64_t added_size = appendToHeader(entry[0]->value(), value, delimiter);
     309          31 :     addSize(added_size);
     310          72 :   } else {
     311          72 :     addCopy(key, value);
     312          72 :   }
     313         103 : }
     314             : 
     315         401 : void HeaderMapImpl::setReference(const LowerCaseString& key, absl::string_view value) {
     316         401 :   remove(key);
     317         401 :   addReference(key, value);
     318         401 : }
     319             : 
     320         239 : void HeaderMapImpl::setReferenceKey(const LowerCaseString& key, absl::string_view value) {
     321         239 :   remove(key);
     322         239 :   addReferenceKey(key, value);
     323         239 : }
     324             : 
     325           5 : void HeaderMapImpl::setCopy(const LowerCaseString& key, absl::string_view value) {
     326           5 :   remove(key);
     327           5 :   addCopy(key, value);
     328           5 : }
     329             : 
     330       38057 : uint64_t HeaderMapImpl::byteSize() const { return cached_byte_size_; }
     331             : 
     332        8648 : void HeaderMapImpl::verifyByteSizeInternalForTest() const {
     333             :   // Computes the total byte size by summing the byte size of the keys and values.
     334        8648 :   uint64_t byte_size = 0;
     335       23281 :   for (const HeaderEntryImpl& header : headers_) {
     336       23281 :     byte_size += header.key().size();
     337       23281 :     byte_size += header.value().size();
     338       23281 :   }
     339        8648 :   ASSERT(cached_byte_size_ == byte_size);
     340        8648 : }
     341             : 
     342        6772 : HeaderMap::GetResult HeaderMapImpl::get(const LowerCaseString& key) const {
     343        6772 :   return HeaderMap::GetResult(const_cast<HeaderMapImpl*>(this)->getExisting(key));
     344        6772 : }
     345             : 
     346        6875 : HeaderMap::NonConstGetResult HeaderMapImpl::getExisting(absl::string_view key) {
     347             :   // Attempt a trie lookup first to see if the user is requesting an O(1) header. This may be
     348             :   // relatively common in certain header matching / routing patterns.
     349             :   // TODO(mattklein123): Add inline handle support directly to the header matcher code to support
     350             :   // this use case more directly.
     351        6875 :   HeaderMap::NonConstGetResult ret;
     352        6875 :   auto lookup = staticLookup(key);
     353        6875 :   if (lookup.has_value()) {
     354        4902 :     if (*lookup.value().entry_ != nullptr) {
     355        2210 :       ret.push_back(*lookup.value().entry_);
     356        2210 :     }
     357        4902 :     return ret;
     358        4902 :   }
     359             : 
     360             :   // If the requested header is not an O(1) header try using the lazy map to
     361             :   // search for it instead of iterating the headers list.
     362        1973 :   if (headers_.maybeMakeMap()) {
     363        1107 :     HeaderList::HeaderLazyMap::iterator iter = headers_.mapFind(key);
     364        1107 :     if (iter != headers_.mapEnd()) {
     365         157 :       const HeaderList::HeaderNodeVector& v = iter->second;
     366         157 :       ASSERT(!v.empty()); // It's impossible to have a map entry with an empty vector as its value.
     367       66224 :       for (const auto& values_it : v) {
     368             :         // Convert the iterated value to a HeaderEntry*.
     369       66224 :         ret.push_back(&(*values_it));
     370       66224 :       }
     371         157 :     }
     372        1107 :     return ret;
     373        1107 :   }
     374             : 
     375             :   // If the requested header is not an O(1) header and the lazy map is not in use, we do a full
     376             :   // scan. Doing the trie lookup is wasteful in the miss case, but is present for code consistency
     377             :   // with other functions that do similar things.
     378         974 :   for (HeaderEntryImpl& header : headers_) {
     379         386 :     if (header.key() == key) {
     380         103 :       ret.push_back(&header);
     381         103 :     }
     382         386 :   }
     383             : 
     384         866 :   return ret;
     385        1973 : }
     386             : 
     387       10098 : void HeaderMapImpl::iterate(HeaderMap::ConstIterateCb cb) const {
     388       30026 :   for (const HeaderEntryImpl& header : headers_) {
     389       30024 :     if (cb(header) == HeaderMap::Iterate::Break) {
     390          15 :       break;
     391          15 :     }
     392       30024 :   }
     393       10098 : }
     394             : 
     395        6737 : void HeaderMapImpl::iterateReverse(HeaderMap::ConstIterateCb cb) const {
     396       21719 :   for (auto it = headers_.rbegin(); it != headers_.rend(); it++) {
     397       14982 :     if (cb(*it) == HeaderMap::Iterate::Break) {
     398           0 :       break;
     399           0 :     }
     400       14982 :   }
     401        6737 : }
     402             : 
     403        1199 : void HeaderMapImpl::clear() {
     404        1199 :   clearInline();
     405        1199 :   headers_.clear();
     406        1199 :   cached_byte_size_ = 0;
     407        1199 : }
     408             : 
     409          67 : size_t HeaderMapImpl::removeIf(const HeaderMap::HeaderMatchPredicate& predicate) {
     410          67 :   const size_t old_size = headers_.size();
     411         101 :   headers_.removeIf([&predicate, this](const HeaderEntryImpl& entry) {
     412         101 :     const bool to_remove = predicate(entry);
     413         101 :     if (to_remove) {
     414             :       // If this header should be removed, make sure any references in the
     415             :       // static lookup table are cleared as well.
     416          25 :       auto lookup = staticLookup(entry.key().getStringView());
     417          25 :       if (lookup.has_value()) {
     418           2 :         if (lookup.value().entry_) {
     419           2 :           const uint32_t key_value_size =
     420           2 :               (*lookup.value().entry_)->key().size() + (*lookup.value().entry_)->value().size();
     421           2 :           subtractSize(key_value_size);
     422           2 :           *lookup.value().entry_ = nullptr;
     423           2 :         }
     424          23 :       } else {
     425          23 :         subtractSize(entry.key().size() + entry.value().size());
     426          23 :       }
     427          25 :     }
     428         101 :     return to_remove;
     429         101 :   });
     430          67 :   return old_size - headers_.size();
     431          67 : }
     432             : 
     433         774 : size_t HeaderMapImpl::remove(const LowerCaseString& key) { return removeExisting(key); }
     434             : 
     435          67 : size_t HeaderMapImpl::removePrefix(const LowerCaseString& prefix) {
     436         101 :   return HeaderMapImpl::removeIf([&prefix](const HeaderEntry& entry) -> bool {
     437         101 :     return absl::StartsWith(entry.key().getStringView(), prefix.get());
     438         101 :   });
     439          67 : }
     440             : 
     441           0 : void HeaderMapImpl::dumpState(std::ostream& os, int indent_level) const {
     442           0 :   iterate([&os,
     443           0 :            spaces = spacesForLevel(indent_level)](const HeaderEntry& header) -> HeaderMap::Iterate {
     444           0 :     os << spaces << "'" << header.key().getStringView() << "', '" << header.value().getStringView()
     445           0 :        << "'\n";
     446           0 :     return HeaderMap::Iterate::Continue;
     447           0 :   });
     448           0 : }
     449             : 
     450             : HeaderMapImpl::HeaderEntryImpl& HeaderMapImpl::maybeCreateInline(HeaderEntryImpl** entry,
     451        8914 :                                                                  const LowerCaseString& key) {
     452        8914 :   if (*entry) {
     453        1324 :     return **entry;
     454        1324 :   }
     455             : 
     456        7590 :   addSize(key.get().size());
     457        7590 :   HeaderNode i = headers_.insert(key);
     458        7590 :   i->entry_ = i;
     459        7590 :   *entry = &(*i);
     460        7590 :   return **entry;
     461        8914 : }
     462             : 
     463             : HeaderMapImpl::HeaderEntryImpl& HeaderMapImpl::maybeCreateInline(HeaderEntryImpl** entry,
     464             :                                                                  const LowerCaseString& key,
     465        9979 :                                                                  HeaderString&& value) {
     466        9979 :   if (*entry) {
     467           0 :     value.clear();
     468           0 :     return **entry;
     469           0 :   }
     470             : 
     471        9979 :   addSize(key.get().size() + value.size());
     472        9979 :   HeaderNode i = headers_.insert(key, std::move(value));
     473        9979 :   i->entry_ = i;
     474        9979 :   *entry = &(*i);
     475        9979 :   return **entry;
     476        9979 : }
     477             : 
     478         774 : size_t HeaderMapImpl::removeExisting(absl::string_view key) {
     479         774 :   const size_t old_size = headers_.size();
     480         774 :   auto lookup = staticLookup(key);
     481         774 :   if (lookup.has_value()) {
     482         114 :     removeInline(lookup.value().entry_);
     483         747 :   } else {
     484         660 :     subtractSize(headers_.remove(key));
     485         660 :   }
     486         774 :   return old_size - headers_.size();
     487         774 : }
     488             : 
     489       14174 : size_t HeaderMapImpl::removeInline(HeaderEntryImpl** ptr_to_entry) {
     490       14174 :   if (!*ptr_to_entry) {
     491       13914 :     return 0;
     492       13914 :   }
     493             : 
     494         260 :   HeaderEntryImpl* entry = *ptr_to_entry;
     495         260 :   const uint64_t size_to_subtract = entry->entry_->key().size() + entry->entry_->value().size();
     496         260 :   subtractSize(size_to_subtract);
     497         260 :   *ptr_to_entry = nullptr;
     498         260 :   headers_.erase(entry->entry_, true);
     499         260 :   return 1;
     500       14174 : }
     501             : 
     502             : namespace {
     503             : template <class T>
     504         536 : HeaderMapImplUtility::HeaderMapImplInfo makeHeaderMapImplInfo(absl::string_view name) {
     505             :   // Constructing a header map implementation will force the custom headers and sizing to be
     506             :   // finalized, so do that first.
     507         536 :   auto header_map = T::create();
     508             : 
     509         536 :   HeaderMapImplUtility::HeaderMapImplInfo info;
     510         536 :   info.name_ = std::string(name);
     511         536 :   info.size_ = T::inlineHeadersSize() + sizeof(T);
     512       11140 :   for (const auto& header : CustomInlineHeaderRegistry::headers<T::header_map_type>()) {
     513       11140 :     info.registered_headers_.push_back(header.first.get());
     514       11140 :   }
     515         536 :   return info;
     516         536 : }
     517             : } // namespace
     518             : 
     519             : std::vector<HeaderMapImplUtility::HeaderMapImplInfo>
     520         134 : HeaderMapImplUtility::getAllHeaderMapImplInfo() {
     521         134 :   std::vector<HeaderMapImplUtility::HeaderMapImplInfo> ret;
     522         134 :   ret.push_back(makeHeaderMapImplInfo<RequestHeaderMapImpl>("request header map"));
     523         134 :   ret.push_back(makeHeaderMapImplInfo<RequestTrailerMapImpl>("request trailer map"));
     524         134 :   ret.push_back(makeHeaderMapImplInfo<ResponseHeaderMapImpl>("response header map"));
     525         134 :   ret.push_back(makeHeaderMapImplInfo<ResponseTrailerMapImpl>("response trailer map"));
     526         134 :   return ret;
     527         134 : }
     528             : 
     529             : } // namespace Http
     530             : } // namespace Envoy

Generated by: LCOV version 1.15