-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
hcm: fix sending local reply during encode + grpc request classification #13256
Conversation
Fixes two issues that surfaced when adding an integration test for the gRPC reverse bridge: 1) when sending a local reply during the encoding path, local_complete_ is set to true which results in endStream being called twice. We fix this by not calling endStream during the header/body callback when local_complete_ is true 2) the direct reply function was not using the state variable to detect is_grpc_request, which meant that for the reverse bridge is was using the modified headers which no longer have a gRPC content type. Signed-off-by: Snow Pettersen <[email protected]>
Locally this seems to work and cause no issues with integration tests, lmk if you want to proceed with this or revert the other PR @mattklein123 |
@zuercher Turns out there was a bug around text/plain as well, because during integration tests we end up taking a different flow and hit code that wasn't checking the state variable but instead checked the request headers that we'd already modified to not be grpc anymore. Lesson to be learnt: integration test it! |
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.
At a high level this makes sense to me. But I would like to see:
- conn_manager_impl unit tests
- non-extension specific integration tests
If it's easier to revert the other PR for now and re-apply with ^ that's fine with me. Thank you!
/wait
source/common/http/filter_manager.cc
Outdated
@@ -880,16 +880,13 @@ void FilterManager::sendDirectLocalReply( | |||
state_.non_100_response_headers_encoded_ = true; | |||
filter_manager_callbacks_.encodeHeaders(*filter_manager_callbacks_.responseHeaders(), | |||
end_stream); | |||
maybeEndEncode(end_stream); | |||
maybeEndEncode(end_stream && !state_.local_complete_); |
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.
Sorry where is local_complete_ set to true? Before the filter chain starts iterating? This is not super intuitive. Can you add more comments?
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.
but why do we need to sometimes end encode after encode headers / encode data, and sometimes outside of the EncodeFunctions? Can't we just remove the one at the end, or remove these two calls?
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.
I looked through the code and I think it was there because the call to encode headers could trigger a reset, in which case encodeData wouldn't be called, so in that case endStream wouldn't be called. Calling reset would call local_complete_, and so endStream would be called at the end of the function.
That said, I tried removing it and no integration tests seem to fail. Seems like doEndStream
is called as part of reset anyways, so it might not be necessary? Pushed this change, so let's see if CI passes
Yeah that's reasonable, let's revert the other PR now to keep HEAD healthy. |
Signed-off-by: Snow Pettersen <[email protected]>
Signed-off-by: Snow Pettersen <[email protected]>
Signed-off-by: Snow Pettersen <[email protected]>
Signed-off-by: Snow Pettersen <[email protected]>
Signed-off-by: Snow Pettersen <[email protected]>
Signed-off-by: Snow Pettersen <[email protected]>
Signed-off-by: Snow Pettersen <[email protected]>
Signed-off-by: Snow Pettersen <[email protected]>
constexpr static char name[] = "local-reply-during-encode"; | ||
|
||
Http::FilterHeadersStatus encodeHeaders(Http::ResponseHeaderMap&, bool) override { | ||
decoder_callbacks_->sendLocalReply(Http::Code::InternalServerError, "", nullptr, absl::nullopt, |
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.
Would it make sense to add sendLocalReply
to the StreamEncoderFilterCallbacks
interface?
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.
+1 per slack convo also
Signed-off-by: Snow Pettersen <[email protected]>
Signed-off-by: Snow Pettersen <[email protected]>
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.
Thanks LGTM other than remaining comments.
/wait
@@ -173,50 +173,5 @@ TEST_P(ReverseBridgeIntegrationTest, EnabledRoute) { | |||
ASSERT_TRUE(fake_upstream_connection_->waitForDisconnect()); | |||
} | |||
|
|||
TEST_P(ReverseBridgeIntegrationTest, EnabledRouteBadContentType) { |
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.
FWIW I don't see the harm of leaving this test.
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.
I was thinking that it wouldn't pass without the other PR but I'm not sure if that's true, I'll try adding it back
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.
Oh sorry I forgot about that. OK if you want to add it back there that's fine.
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.
I was able to get it working, seems like it just tested an existing feature so it passes now and should nicely serve as a regression test to make sure that we're not breaking this feature with the change to use sendLocalReply in the future
constexpr static char name[] = "local-reply-during-encode"; | ||
|
||
Http::FilterHeadersStatus encodeHeaders(Http::ResponseHeaderMap&, bool) override { | ||
decoder_callbacks_->sendLocalReply(Http::Code::InternalServerError, "", nullptr, absl::nullopt, |
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.
+1 per slack convo also
This reverts commit 2f4d2f6. Signed-off-by: Snow Pettersen <[email protected]>
Signed-off-by: Snow Pettersen <[email protected]>
Signed-off-by: Snow Pettersen <[email protected]>
Signed-off-by: Snow Pettersen <[email protected]>
Signed-off-by: Snow Pettersen <[email protected]>
Signed-off-by: Snow Pettersen <[email protected]>
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.
Awesome, thanks!
/retest |
Retrying Azure Pipelines, to retry CircleCI checks, use |
@alyssawilk do you wanna take a look at this as well? |
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.
Looks good overall! Really only the one question and the test nits.
source/common/http/filter_manager.cc
Outdated
@@ -880,16 +880,13 @@ void FilterManager::sendDirectLocalReply( | |||
state_.non_100_response_headers_encoded_ = true; | |||
filter_manager_callbacks_.encodeHeaders(*filter_manager_callbacks_.responseHeaders(), | |||
end_stream); | |||
maybeEndEncode(end_stream); | |||
maybeEndEncode(end_stream && !state_.local_complete_); |
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.
but why do we need to sometimes end encode after encode headers / encode data, and sometimes outside of the EncodeFunctions? Can't we just remove the one at the end, or remove these two calls?
ASSERT_TRUE(upstream_request_->waitForEndStream(*dispatcher_)); | ||
|
||
// Ensure that we stripped the length prefix and set the appropriate headers. | ||
EXPECT_EQ("f", upstream_request_->body().toString()); |
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.
I think a bunch of these are tested in another test.
WDYT of just using sendRequestAndWaitForReponse() and cutting out all the duplicate stuff?
|
||
// Wait for the upstream request and begin sending a response with end_stream = false. | ||
waitForNextUpstreamRequest(); | ||
upstream_request_->encodeHeaders(Http::TestResponseHeaderMapImpl{{":status", "503"}}, true); |
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.
again I think you can just sendRequestAndWaitForResponse with default request and response headers, since all you want to do is make sure the status code is set correctly.
Signed-off-by: Snow Pettersen <[email protected]>
Signed-off-by: Snow Pettersen <[email protected]>
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.
LGTM modulo ci investigation
/retests |
/retest |
Retrying Azure Pipelines, to retry CircleCI checks, use |
Fixes two issues that surfaced when adding an integration test for the
gRPC reverse bridge:
is set to true which results in endStream being called twice. We fix
this by not calling endStream during the header/body callback when
local_complete_ is true
is_grpc_request, which meant that for the reverse bridge is was using
the modified headers which no longer have a gRPC content type.
Signed-off-by: Snow Pettersen [email protected]
Risk Level: Medium, HCM changes
Testing: New integration test
Docs Changes: n/a
Release Notes: n/a