diff --git a/source/common/http/BUILD b/source/common/http/BUILD index 8fd46d8d58dc..5e78b0ed8def 100644 --- a/source/common/http/BUILD +++ b/source/common/http/BUILD @@ -253,6 +253,15 @@ envoy_cc_library( ], ) +envoy_cc_library( + name = "header_list_view_lib", + srcs = ["header_list_view.cc"], + hdrs = ["header_list_view.h"], + deps = [ + "//include/envoy/http:header_map_interface", + ], +) + envoy_cc_library( name = "header_map_lib", srcs = ["header_map_impl.cc"], diff --git a/source/common/http/header_list_view.cc b/source/common/http/header_list_view.cc new file mode 100644 index 000000000000..a29bc84bf86f --- /dev/null +++ b/source/common/http/header_list_view.cc @@ -0,0 +1,19 @@ +#include "common/http/header_list_view.h" + +namespace Envoy { +namespace Http { + +HeaderListView::HeaderListView(const HeaderMap& header_map) { + header_map.iterate( + [](const Http::HeaderEntry& header, void* context) -> HeaderMap::Iterate { + auto* context_ptr = static_cast(context); + context_ptr->keys_.emplace_back(std::reference_wrapper(header.key())); + context_ptr->values_.emplace_back( + std::reference_wrapper(header.value())); + return HeaderMap::Iterate::Continue; + }, + this); +} + +} // namespace Http +} // namespace Envoy \ No newline at end of file diff --git a/source/common/http/header_list_view.h b/source/common/http/header_list_view.h new file mode 100644 index 000000000000..552af6f89d5c --- /dev/null +++ b/source/common/http/header_list_view.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +#include "envoy/http/header_map.h" + +namespace Envoy { +namespace Http { + +class HeaderListView { +public: + using HeaderStringRefs = std::vector>; + + HeaderListView(const HeaderMap& header_map); + const HeaderStringRefs& keys() const { return keys_; } + const HeaderStringRefs& values() const { return values_; } + +private: + HeaderStringRefs keys_; + HeaderStringRefs values_; +}; + +} // namespace Http +} // namespace Envoy diff --git a/test/common/http/BUILD b/test/common/http/BUILD index b5b736ff1fc4..3f9e7fcb3715 100644 --- a/test/common/http/BUILD +++ b/test/common/http/BUILD @@ -278,6 +278,7 @@ envoy_cc_test( name = "header_map_impl_test", srcs = ["header_map_impl_test.cc"], deps = [ + "//source/common/http:header_list_view_lib", "//source/common/http:header_map_lib", "//source/common/http:header_utility_lib", "//test/test_common:utility_lib", diff --git a/test/common/http/header_map_impl_test.cc b/test/common/http/header_map_impl_test.cc index b28c7a016283..5bb93d8300e3 100644 --- a/test/common/http/header_map_impl_test.cc +++ b/test/common/http/header_map_impl_test.cc @@ -1,6 +1,8 @@ +#include #include #include +#include "common/http/header_list_view.h" #include "common/http/header_map_impl.h" #include "common/http/header_utility.h" @@ -9,6 +11,7 @@ #include "gtest/gtest.h" +using ::testing::ElementsAre; using ::testing::InSequence; namespace Envoy { @@ -920,6 +923,24 @@ TEST(HeaderMapImplTest, Get) { } } +TEST(HeaderMapImplTest, TestHeaderList) { + std::array keys{Headers::get().Path, LowerCaseString("hello")}; + std::array values{"/", "world"}; + + auto headers = createHeaderMap({{keys[0], values[0]}, {keys[1], values[1]}}); + HeaderListView header_list(headers->header_map_); + auto to_string_views = + [](const HeaderListView::HeaderStringRefs& strs) -> std::vector { + std::vector str_views(strs.size()); + std::transform(strs.begin(), strs.end(), str_views.begin(), + [](auto value) -> absl::string_view { return value.get().getStringView(); }); + return str_views; + }; + + EXPECT_THAT(to_string_views(header_list.keys()), ElementsAre(":path", "hello")); + EXPECT_THAT(to_string_views(header_list.values()), ElementsAre("/", "world")); +} + TEST(HeaderMapImplTest, TestAppendHeader) { // Test appending to a string with a value. {