Skip to content

router: send response_headers_to_add with direct responses#2458

Merged
mattklein123 merged 9 commits intoenvoyproxy:masterfrom
brian-pane:direct-response-headers/2315
Jan 30, 2018
Merged

router: send response_headers_to_add with direct responses#2458
mattklein123 merged 9 commits intoenvoyproxy:masterfrom
brian-pane:direct-response-headers/2315

Conversation

@brian-pane
Copy link
Copy Markdown
Contributor

@brian-pane brian-pane commented Jan 26, 2018

Description:
Send any configured response_headers_to_add with direct responses.

Risk Level: Medium

Testing: New integration test included

Docs Changes: envoyproxy/data-plane-api#436

Release Notes: Included in this PR

Fixes: #2315

API Changes: envoyproxy/data-plane-api#393

Signed-off-by: Brian Pane bpane@pinterest.com

*Description*:
Send any configured `response_headers_to_add` with direct responses.

*Risk Level*: Medium

*Testing*: New integration test included

*Docs Changes*: TODO

*Release Notes*: Included in this PR

*Fixes*: #2315

*API Changes*: envoyproxy/data-plane-api#393

Signed-off-by: Brian Pane <bpane@pinterest.com>
@brian-pane
Copy link
Copy Markdown
Contributor Author

I still need to write the documentation for this feature. I'll make a doc PR and link to it here.

config_.stats_.rq_redirect_.inc();
Http::Utility::sendRedirect(*callbacks_, route_->directResponseEntry()->newPath(headers),
response_code);
Http::Utility::sendRedirect(*callbacks_, direct_response->newPath(headers), response_code);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is there a reason why 3xx responses don't get extra headers and response body?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That's for backward compatibility. The implementations of the new direct-response feature and the existing redirect feature were merged in PR2335, at the request of the reviewers. Thus, if we were to send the extra headers with 3xx responses, it could change the behavior of users' existing Envoy configurations.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggestion here (without full review): I still think we could probably pull the trigger and just do it in all cases and no one would notice, but if we feel that we shouldn't do that, I would put the fact that we are deprecating the old behavior in DEPRECATED.md and put a comment here. We can remove the guard in the next release.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hmm, sending the headers and response body in all cases would definitely yield a more consistent feature. I'll update this PR to make 3xx work the same way as all other response statuses.

…mit to both file and inline response bodies

Signed-off-by: Brian Pane <bpane@pinterest.com>
Copy link
Copy Markdown
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

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

Generally looks great to me. A few minor comments. Thank you!

virtual ~ResponseEntry() {}

/**
* Do potentially destructive header transforms on response headers prior to forwarding. For
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

"For example" ?

return Http::FilterHeadersStatus::StopIteration;
}
const auto* direct_response = route_->directResponseEntry();
const auto& request_headers = headers;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why do you need this variable? Is this just for the capture? can you just capture the headers reference directly?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The lambda has its own function parameter named headers, so this is just an alias to prevent a name collision.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

ah OK. FYI you can use C++14 lambda capture expression to define this variable inline in the capture which is a bit cleaner.

bool end_stream) -> void {
const auto new_path = direct_response->newPath(request_headers);
if (!new_path.empty()) {
headers->addCopy(Http::LowerCaseString("location"), new_path);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You can do this using O(1) headers by doing a variant of headers->insertLocation()...

Copy link
Copy Markdown
Contributor Author

@brian-pane brian-pane Jan 26, 2018

Choose a reason for hiding this comment

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

It looks like Location isn't configured as one of the O(1) headers in header_map.h. I suppose I could add it, but it looks like each new header configured for O(1) access adds another pointer field to the HeaderMapImpl ... is it okay to increase the size of that structure?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ah OK, sorry. It's not a big deal either way. But you can use the constant that is already in Http::Headers and then addReferenceKey

EXPECT_EQ(Http::Code::OK, direct_response->responseCode());
EXPECT_STREQ("content", direct_response->responseBody().c_str());

std::string response_body(4097, 'A');
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: I might split this into a separate test with a more obvious name.

}
}

TEST(RouteConfigurationV2, DirectResponse) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For new tests please add a // comment with a brief description of what the test does.

Brian Pane added 2 commits January 27, 2018 00:04
Signed-off-by: Brian Pane <bpane@pinterest.com>
Signed-off-by: Brian Pane <bpane@pinterest.com>
Copy link
Copy Markdown
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.

Looks good - only two questions on my end.

auto response_code = route_->directResponseEntry()->responseCode();
if (response_code >= Http::Code::MultipleChoices && response_code < Http::Code::BadRequest) {
config_.stats_.rq_redirect_.inc();
Http::Utility::sendRedirect(*callbacks_, route_->directResponseEntry()->newPath(headers),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can we remove sendRedirect with this PR?

sendLocalReply(route_->directResponseEntry()->responseCode(),
route_->directResponseEntry()->responseBody(), false);
// TODO(brian-pane) support sending response_headers_to_add.
Http::Utility::sendLocalReply(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is very similar to the existing Filter::sendLocalReply. Could we extend that instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, I think I have a way to make that work. Update coming soon.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I removed the overloaded parameter from Http::Filter::sendLocalReply and replaced it with a more general callback hook to modify the headers. That made the couple of existing calls to that method more verbose, but I think it's a net improvement.

Brian Pane added 2 commits January 30, 2018 01:44
Signed-off-by: Brian Pane <bpane@pinterest.com>
Signed-off-by: Brian Pane <bpane@pinterest.com>
@alyssawilk
Copy link
Copy Markdown
Contributor

Did you miss one user of the function? It looks like some of the builds are unhappy.
Also you'll need a master merge at some point but no hurry on that one.

Signed-off-by: Brian Pane <bpane@pinterest.com>
->void {
const auto new_path = direct_response->newPath(request_headers);
if (!new_path.empty()) {
response_headers.addCopy(Http::LowerCaseString("location"), new_path);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

My previous comment on this still needs action just in case it got lost (switch to addReferenceKey and use the constant in the headers class).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

There isn't a constant for location in the headers class:

$ egrep -ir location include/envoy/http
$ echo $?
1
$

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Oh, wait you mean the other headers class, the one in source/common/http.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, sorry, was going to provide you link. Basically just look at how it's being used in the other redirect code.

…eaders/2315

Conflicts:
	RAW_RELEASE_NOTES.md
	source/common/router/config_utility.cc

Signed-off-by: Brian Pane <bpane@pinterest.com>
Copy link
Copy Markdown
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.

Thanks for the refactor and adding comments! LGTM modulo one final nit.

* @param code supplies the HTTP status code.
* @param body supplies the response body (empty string if no body is needed).
* @param add_headers supplies an optional callback function that can add additional
* headers to the response.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

that can alter the headers in the response
since it could also theoretically remove or just change, yeah?

Signed-off-by: Brian Pane <bpane@pinterest.com>
Copy link
Copy Markdown
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

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

very nice, thanks.

@mattklein123 mattklein123 merged commit 788faa2 into envoyproxy:master Jan 30, 2018
Shikugawa pushed a commit to Shikugawa/envoy that referenced this pull request Mar 28, 2020
* add usage of stackdriver logger and test

* add stat prefix

* add metrics and only export at server

* remove timeseries.go

* fix test due to merge conflict
jpsim pushed a commit that referenced this pull request Nov 28, 2022
Signed-off-by: JP Simard <jp@jpsim.com>
jpsim pushed a commit that referenced this pull request Nov 29, 2022
Signed-off-by: JP Simard <jp@jpsim.com>
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.

4 participants