Skip to content
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

http: adding an interface to inform filters of local replies #15172

Merged
merged 11 commits into from
Mar 8, 2021

Conversation

alyssawilk
Copy link
Contributor

Risk Level: low (no-op for most filters)
Testing: new integration test. NEEDS UNIT TESTS
Docs Changes: n/a
Release Notes: TBD
Fixes #14791

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@alyssawilk
Copy link
Contributor Author

Hey @goaway WDYT of this as a start?

Looking for high level suggestions (do we need other return options? more data in the struct? better naming?) and once I have your thumbs up I'll add unit tests and send it to the maintainers for review.

goaway
goaway previously approved these changes Feb 24, 2021
Copy link
Contributor

@goaway goaway left a comment

Choose a reason for hiding this comment

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

Wow, thank you for putting something together so quickly! This looks great, and I do think it gives us everything we need.

I don't immediately see a need for any extra data; we surface errors with an error code and a message, which has a direct corollary to the HTTP status code and body. The only thing I wonder is if introducing a different raiseStreamError interface might allow for more nuanced status codes than what HTTP affords in some cases.

But that also seems like something we could consider separately - today we map HTTP code to an error code anyways so this would still be a big improvement for us.

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@alyssawilk alyssawilk marked this pull request as ready for review March 1, 2021 21:46
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@alyssawilk
Copy link
Contributor Author

ping!

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Copy link
Contributor

@snowp snowp left a comment

Choose a reason for hiding this comment

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

Thanks this looks pretty good and not too complicated.

Curious what you think about @goaway's suggestion of an error API that would allow us to semantically differentiate a local reply used as a helper to respond (e.g. https://github.com/envoyproxy/envoy/blob/main/source/extensions/filters/http/health_check/health_check.cc#L179-L186) vs stream errors (https://github.com/envoyproxy/envoy/blob/main/source/common/router/router.cc#L659-L661).

I think this could probably be solved by just having a bool streamError() const on StreamInfo and having a wrapper around sendLocalReply that sets this value for the error cases, but curious if you think it's worth integrating this into the onLocalReply API more tightly.

Comment on lines +173 to +174
// Continue sending onLocalReply to all filters, but reset the stream once all filters have been
// informed rather than sending the local reply.
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we have some way of indicating to filters that the local reply is going to be reset? I can imagine filters wanting to do some mutation of the local reply in some cases, but it doesn't make sense for them to do this if a previous filter has triggered a reset

Copy link
Contributor Author

Choose a reason for hiding this comment

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

they can't mutate the local reply here, only from the actual sendlocalReply, but can't hurt to pass on that info

include/envoy/http/filter.h Outdated Show resolved Hide resolved
include/envoy/http/filter.h Show resolved Hide resolved
Comment on lines +841 to +842
ENVOY_STREAM_LOG(debug, "Resetting stream due to {}. onLocalReply requested reset.", *this,
details);
Copy link
Contributor

Choose a reason for hiding this comment

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

Any way we can capture which filter is triggering the reset? Or let the filter that triggers a reset include information?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I mean we don't really for sendLocalReply logs either, right?

Copy link
Contributor

Choose a reason for hiding this comment

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

At least with local replies we can infer it from the response code details, but yea I don't think this is necessary, just a nice to have

@@ -760,6 +760,7 @@ class FilterManager : public ScopeTrackedObject,
// Http::FilterChainFactoryCallbacks
void addStreamDecoderFilter(StreamDecoderFilterSharedPtr filter) override {
addStreamDecoderFilterWorker(filter, nullptr, false);
filters_.push_back(filter.get());
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we document the order in which filters are given the callback? Seems like the order is first added to last added, regardless of whether it was a decoder or encoder filter. I think people might intuitively expect this to follow the decoder or encoder filter chains, but currently this can interleave between the two.

I think with the current impl the order doesn't matter at all, but I can imagine iterations of this feature (like my suggestion of capturing information about which filter is doing the reset) where it starts mattering.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure, added to include.

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Copy link
Contributor Author

@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.

I think this is what @goaway described at the mobile meeting. We could always make the hcm sendLocalReply be an overridable function and have envoy mobile override it, but I think there was some desire to have filters be informed that a reply is imminent, without actually sending the reply. There's also the complexities of sendLocalReply usually generating a reply but sometimes doing direct-encode or rst where I think this results in a simpler and harder-to-screw-up interface. I'm up for whatever though :-)

Comment on lines +841 to +842
ENVOY_STREAM_LOG(debug, "Resetting stream due to {}. onLocalReply requested reset.", *this,
details);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I mean we don't really for sendLocalReply logs either, right?

@@ -760,6 +760,7 @@ class FilterManager : public ScopeTrackedObject,
// Http::FilterChainFactoryCallbacks
void addStreamDecoderFilter(StreamDecoderFilterSharedPtr filter) override {
addStreamDecoderFilterWorker(filter, nullptr, false);
filters_.push_back(filter.get());
Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure, added to include.

Comment on lines +173 to +174
// Continue sending onLocalReply to all filters, but reset the stream once all filters have been
// informed rather than sending the local reply.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

they can't mutate the local reply here, only from the actual sendlocalReply, but can't hurt to pass on that info

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@goaway
Copy link
Contributor

goaway commented Mar 3, 2021

Just to clarify - the ability to override sendLocalReply or some antecedent call was mostly just a suggestion about one possible approach. I think the approach here works great though - the main requirement is to have an unambiguous signal that filters get to see regardless of whether a local reply ends up traversing the filter chain.

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
@alyssawilk
Copy link
Contributor Author

@snowp the mac failure is the known timeout, and other comments addressed. PTAL when you get a chance!

Copy link
Contributor

@snowp snowp left a comment

Choose a reason for hiding this comment

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

LGTM besides the one comment comment

Comment on lines 625 to 626
* This will be called on both encoder and decoder filters starting at the
* router filter and working towards the first filter configured.
Copy link
Contributor

Choose a reason for hiding this comment

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

In theory someone could be using another terminal filter that isn't the router filter and still make use of local replies right? Maybe make this "at the terminal filter"

Signed-off-by: Alyssa Wilk <alyssar@chromium.org>
Copy link
Contributor

@snowp snowp left a comment

Choose a reason for hiding this comment

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

Thanks!

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.

Error Pathway
3 participants