-
Notifications
You must be signed in to change notification settings - Fork 5.5k
ensure that the inline cookie header will be folded correctly #17560
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
0da881f
0b12394
56027f0
58659ad
8703819
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,6 +46,13 @@ bool validatedLowerCaseString(absl::string_view str) { | |
| return lower_case_str == str; | ||
| } | ||
|
|
||
| absl::string_view delimiterByHeader(const LowerCaseString& key, bool correctly_coalesce_cookies) { | ||
| if (correctly_coalesce_cookies && key == Http::Headers::get().Cookie) { | ||
| return "; "; | ||
| } | ||
| return ","; | ||
| } | ||
|
|
||
| } // namespace | ||
|
|
||
| // Initialize as a Type::Inline | ||
|
|
@@ -368,8 +375,10 @@ void HeaderMapImpl::insertByKey(HeaderString&& key, HeaderString&& value) { | |
| if (*lookup.value().entry_ == nullptr) { | ||
| maybeCreateInline(lookup.value().entry_, *lookup.value().key_, std::move(value)); | ||
| } else { | ||
| auto delimiter = | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: const
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. get it. |
||
| delimiterByHeader(*lookup.value().key_, header_map_correctly_coalesce_cookies_); | ||
| const uint64_t added_size = | ||
| appendToHeader((*lookup.value().entry_)->value(), value.getStringView()); | ||
| appendToHeader((*lookup.value().entry_)->value(), value.getStringView(), delimiter); | ||
|
alyssawilk marked this conversation as resolved.
|
||
| addSize(added_size); | ||
| value.clear(); | ||
| } | ||
|
|
@@ -434,10 +443,8 @@ void HeaderMapImpl::appendCopy(const LowerCaseString& key, absl::string_view val | |
| // TODO(#9221): converge on and document a policy for coalescing multiple headers. | ||
| auto entry = getExisting(key); | ||
| if (!entry.empty()) { | ||
| const std::string delimiter = (key == Http::Headers::get().Cookie ? "; " : ","); | ||
| const uint64_t added_size = header_map_correctly_coalesce_cookies_ | ||
| ? appendToHeader(entry[0]->value(), value, delimiter) | ||
| : appendToHeader(entry[0]->value(), value); | ||
| auto delimiter = delimiterByHeader(key, header_map_correctly_coalesce_cookies_); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: const
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. get it. |
||
| const uint64_t added_size = appendToHeader(entry[0]->value(), value, delimiter); | ||
| addSize(added_size); | ||
| } else { | ||
| addCopy(key, value); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| #include "source/common/http/header_map_impl.h" | ||
| #include "source/common/http/header_utility.h" | ||
|
|
||
| #include "test/mocks/runtime/mocks.h" | ||
| #include "test/test_common/utility.h" | ||
|
|
||
| #include "gtest/gtest.h" | ||
|
|
||
| namespace Envoy { | ||
| namespace Http { | ||
| namespace { | ||
|
|
||
| // Test that the cookie header can work correctly after being registered as an inline header. The | ||
| // test will register the cookie as an inline header. In order to avoid affecting other tests, the | ||
| // test is placed in this separate source file. | ||
| TEST(InlineCookieTest, InlineCookieTest) { | ||
| Http::CustomInlineHeaderRegistry::registerInlineHeader<Http::RequestHeaderMap::header_map_type>( | ||
| Http::Headers::get().Cookie); | ||
| Http::CustomInlineHeaderRegistry::registerInlineHeader<Http::RequestHeaderMap::header_map_type>( | ||
| Http::LowerCaseString("header_for_compare")); | ||
|
|
||
| auto mock_snapshot = std::make_shared<testing::NiceMock<Runtime::MockSnapshot>>(); | ||
| testing::NiceMock<Runtime::MockLoader> mock_loader; | ||
| Runtime::LoaderSingleton::initialize(&mock_loader); | ||
|
|
||
| { | ||
| // Enable 'envoy.reloadable_features.header_map_correctly_coalesce_cookies' feature. | ||
| ON_CALL(mock_loader, threadsafeSnapshot()).WillByDefault(testing::Return(mock_snapshot)); | ||
| ON_CALL(*mock_snapshot, runtimeFeatureEnabled(_)).WillByDefault(testing::Return(true)); | ||
|
|
||
| Http::TestRequestHeaderMapImpl headers{{"cookie", "key1:value1"}, | ||
| {"cookie", "key2:value2"}, | ||
| {"header_for_compare", "value1"}, | ||
| {"header_for_compare", "value2"}}; | ||
|
|
||
| // Delimiter for inline 'cookie' header is specialized '; '. | ||
| EXPECT_EQ("key1:value1; key2:value2", headers.get_("cookie")); | ||
| // Delimiter for inline 'header_for_compare' header is default ','. | ||
| EXPECT_EQ("value1,value2", headers.get_("header_for_compare")); | ||
| } | ||
|
|
||
| { | ||
| // Disable 'envoy.reloadable_features.header_map_correctly_coalesce_cookies' feature. | ||
| ON_CALL(mock_loader, threadsafeSnapshot()).WillByDefault(testing::Return(mock_snapshot)); | ||
| ON_CALL(*mock_snapshot, runtimeFeatureEnabled(_)).WillByDefault(testing::Return(false)); | ||
|
|
||
| Http::TestRequestHeaderMapImpl headers{{"cookie", "key1:value1"}, | ||
| {"cookie", "key2:value2"}, | ||
| {"header_for_compare", "value1"}, | ||
| {"header_for_compare", "value2"}}; | ||
|
|
||
| // 'envoy.reloadable_features.header_map_correctly_coalesce_cookies' is disabled then default | ||
| // ',' will be used as delimiter. | ||
| EXPECT_EQ("key1:value1,key2:value2", headers.get_("cookie")); | ||
| EXPECT_EQ("value1,value2", headers.get_("header_for_compare")); | ||
| } | ||
| } | ||
|
|
||
| } // namespace | ||
| } // namespace Http | ||
| } // namespace Envoy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perf nit: I don't know if the compiler is smart enough to make the string_view ahead of time, so this might require a strlen each time. I would define constant string_view and then return them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Get it.