Skip to content

test: use TestRequestHeaderMapImpl for building custom headers#2455

Merged
alyssawilk merged 11 commits intoenvoyproxy:mainfrom
caschoener:use-builder
Aug 8, 2022
Merged

test: use TestRequestHeaderMapImpl for building custom headers#2455
alyssawilk merged 11 commits intoenvoyproxy:mainfrom
caschoener:use-builder

Conversation

@caschoener
Copy link
Contributor

@caschoener caschoener commented Aug 3, 2022

In the commit #2362 we added a custom_headers_ field on the BaseClientIntegrationTest class to use for custom headers.

This commit replaces that class field by instead instantiating a custom_headers object inside tests when necessary. Then adds a helper function to convert it from the TestRequestHeaderMapImpl (an easy to edit type) to RequestHeaders (envoy header type).

Signed-off-by: caschoener schoener@google.com

Signed-off-by: caschoener <schoener@google.com>

dos

Signed-off-by: caschoener <schoener@google.com>
namespace Http {
namespace Utility {

void toEnvoyHeaders(HeaderMap& transformed_headers, envoy_headers headers) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The edits to this file aren't strictly part of this diff. I just noticed that the toEnvoyHeaders function has better parameter names in its header_utility.h file, figured I'd fix the mismatch.

Signed-off-by: caschoener <schoener@google.com>
@alyssawilk alyssawilk self-assigned this Aug 3, 2022
@caschoener caschoener marked this pull request as draft August 3, 2022 21:19
Signed-off-by: caschoener <schoener@google.com>
Signed-off-by: caschoener <schoener@google.com>
Signed-off-by: caschoener <schoener@google.com>
@caschoener caschoener marked this pull request as ready for review August 3, 2022 22:52
Copy link
Contributor

@alyssawilk alyssawilk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sweet! Very excited to see that hacky custom header map go away :-)

for (auto i = 0; i < raw_headers.length; i++) {
auto key = Data::Utility::copyToString(raw_headers.entries[i].key);
auto value = Data::Utility::copyToString(raw_headers.entries[i].value);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like changes to this file can be reverted?

envoy_headers envoyHeaders = Http::Utility::toBridgeHeaders(request_headers);
Platform::RawHeaderMap rawHeaderMap = Platform::envoyHeadersAsRawHeaderMap(envoyHeaders);

Platform::RequestHeadersBuilder builder(Platform::RequestMethod::GET, scheme_, host, "/");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we actually want to get the scheme and host and path from the request headers, which may mean setting the host and scheme in default_request_headers in the test set up (like they were before)
it's rare but a useful corner case to be able to test http schemed requests over a TLS conection

Platform::RawHeaderMap rawHeaderMap = Platform::envoyHeadersAsRawHeaderMap(envoyHeaders);

Platform::RequestHeadersBuilder builder(Platform::RequestMethod::GET, scheme_, host, "/");
for (const auto& pair : rawHeaderMap) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we do something like
header_map.iterate(
[&request_headers, builder](const HeaderEntry& header) -> HeaderMap::Iterate {
}
to get the key/value pairs from request_headers and stick them in builder without doing the above conversions?

void threadRoutine(absl::Notification& engine_running);
// Must be called manually by subclasses in their TearDown();
void TearDown();
std::shared_ptr<Platform::RequestHeaders>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment?


Buffer::OwnedImpl request_data = Buffer::OwnedImpl("request body");
Http::TestRequestHeaderMapImpl custom_headers;
HttpTestUtility::addDefaultHeaders(custom_headers);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can use default_request_headers_ and make sure we addDefaultHeaders in initialize() to avoid having to create headers in each test case

std::string upstream_request;
EXPECT_TRUE(upstream_connection->waitForData(FakeRawConnection::waitForInexactMatch("GET /"),
&upstream_request));

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: always good to revert non-necessary changes just to reduce churn :-)

if (upstreamProtocol() == Http::CodecType::HTTP2) {
builder.addUpstreamHttpProtocol(Platform::UpstreamHttpProtocol::HTTP2);
}
default_request_headers_ = std::make_shared<Platform::RequestHeaders>(builder.build());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want to move default_request_headers_ to be a TestRequestHeaderMap impl, and shift all the tests over to using the new utility.

Signed-off-by: caschoener <schoener@google.com>
Signed-off-by: caschoener <schoener@google.com>
Signed-off-by: caschoener <schoener@google.com>
Signed-off-by: caschoener <schoener@google.com>
Copy link
Contributor

@alyssawilk alyssawilk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wohoo! Almost there

Platform::RequestHeadersBuilder builder(
Platform::RequestMethod::GET,
std::string(default_request_headers_.Scheme()->value().getStringView()),
std::string(default_request_headers_.Host()->value().getStringView()), "/");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's get path from the headers as well?

request_headers.formatter().value();
key_val = formatter.format(key_val);
}
auto key = std::string(key_val);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't key_val already a string? Why do we need the extra one?

builder.set(pair.first, pair.second);
}
auto mobile_headers = std::make_shared<Platform::RequestHeaders>(builder.build());
return mobile_headers;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: consider skipping the temporary variable and just return the make_shared

"envoy.extensions.http.header_formatters.preserve_case.v3.PreserveCaseFormatterConfig");
ConfigHelper::setProtocolOptions(*bootstrap.mutable_static_resources()->mutable_clusters(0),
protocol_options);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need this? Envoy defaults should include stateful formatter

Signed-off-by: caschoener <schoener@google.com>
Copy link
Contributor

@abeyad abeyad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good Chris, thanks for working on this! Left a couple comments.

builder.set(entry.first, values);
}
HttpTestUtility::addDefaultHeaders(default_request_headers_);
default_request_headers_.setHost(fake_upstreams_[0]->localAddress()->asStringView());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is setHost on default_request_headers_ called after adding the default request headers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addDefaultHeaders is really just an initialization function, which sets host to "/" I believe. And then we overwrite the values afterwards.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, thanks for clarifying. The addDefaultHeaders name was a bit confusing, wonder if something like setDefaultHeaderValues would make more sense, but in any case, that's not something for this PR.


for (const auto& pair : rawHeaderMap) {
builder.set(pair.first, pair.second);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I follow L117-133. In L117, we iterate over request_headers, and add them to the RequestHeadersBuilder. In L131, we iterate over the rawHeaderMap and add them to the RequestHeadersBuilder. But the rawHeaderMap is built from envoy_headers which is built from request_headers, so aren't we adding the same headers to the RequestHeadersBuilder twice?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great catch yeah looks like I forgot to delete some code :O

Signed-off-by: caschoener <schoener@google.com>
Copy link
Contributor

@abeyad abeyad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@alyssawilk alyssawilk merged commit 7c44507 into envoyproxy:main Aug 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants