-
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
wasm: Add data buffering for chunks #36411
Conversation
Signed-off-by: Juan Manuel Ollé <[email protected]>
/retest |
Ack. I am a bit overloaded at the moment but will review this evening. |
@mpwarres ping? |
This looks good to me. Will wait for @mpwarres review and then commit /wait-any |
if (buffering_request_body_) { | ||
decoder_callbacks_->addDecodedData(data, false); | ||
} |
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 this will make the final output contains repeated data piece?
/wait
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 wasn't familiar with that function. and when try to understand where it was used and for what, I found this comment
https://github.com/envoyproxy/envoy/blob/main/source/server/admin/admin_filter.cc#L25
in our case streamming is a supported scenario and that is the reason it is only dumped in buffering scenario
I think I have that scenario covered with the test I have added. the one add at the end of the body '.0'
if other. scenario is not covered let me know I could add a test for that.
I made the suite for http and http/2 because this issue is not happening in http1, it seams the library is always sending the last chunk containing end_of_stream with 0 bytes.
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.
the addDecodedData use the move semantics. So, yeah, then this should be safe. I will take a more detailed look this night.
auto request_body = std::vector<std::string>{{"request_"}, {"body"}}; | ||
auto upstream_response_body = std::vector<std::string>{{"upstream_"}, {"body"}}; |
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.
could we add a test with 3 (or more) pieces?
For the first piece, the addDecodedData won't be called before it haven't enter the buffering mode.
For the second piece, the addDecodeData will be called but it's not the ending, so, the filter chain will still be stoped to handle the empty piece (the piece has been moved by the addDecodedData).
For the third piece, the addDecodedData will be called and it the ending, so the filter chain will continue.
One comment to the test. Other things are fine. Thanks for this great fix. 🌷 |
Signed-off-by: Juan Manuel Ollé <[email protected]>
ping for @mpwarres for final review. |
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, just minor/cosmetic comments. Thanks!
@@ -1801,7 +1807,7 @@ Http::FilterDataStatus Context::encodeData(::Envoy::Buffer::Instance& data, bool | |||
buffering_response_body_ = false; | |||
switch (result) { | |||
case Http::FilterDataStatus::Continue: | |||
request_body_buffer_ = nullptr; | |||
response_body_buffer_ = nullptr; |
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 for catching this as well.
logBody(type); | ||
if (end_of_stream) { | ||
getBufferStatus(type, &size, &flags); | ||
setBuffer(type, size, 0, ".0"); |
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.
(optional) nit: for consistency with other operation handling in this plugin, where descriptive text (e.g. "partial.replace") is used as the data that is inserted, you might consider using ".end" or ".appended" instead of ".0".
@@ -12,13 +12,21 @@ namespace { | |||
|
|||
class WasmFilterIntegrationTest | |||
: public HttpIntegrationTest, | |||
public testing::TestWithParam<std::tuple<std::string, std::string, bool>> { | |||
public testing::TestWithParam< | |||
std::tuple<std::tuple<std::string, std::string, bool>, Http::CodecType>> { |
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.
optional: you could define a helper function similar to wasmDualFilterTestMatrix to allow the test to use a flat tuple<std::string, std::string, bool, Http::CodecType> rather than nesting tuples, which gets a little awkward with the nested std::get<>s.
static std::string | ||
testParamsToString(const ::testing::TestParamInfo< | ||
std::tuple<std::tuple<std::string, std::string, bool>, Http::CodecType>>& p) { | ||
return fmt::format("{}_{}_{}_{}", std::get<2>(std::get<0>(p.param)) ? "downstream" : "upstream", |
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.
optional: if you decide to stick with nested tuples for test params, structured bindings might make this a little easier to read, e.g.
auto [wasm_test_params, codec] = p.param;
auto [runtime, language, direction] = wasm_test_params;
return fmt::format("{}_{}_{}_{}", direction ? "downstream" : "upstream", runtime, language, ...);
Signed-off-by: Juan Manuel Ollé <[email protected]>
Signed-off-by: Juan Manuel Ollé <[email protected]>
Signed-off-by: Juan Manuel Ollé <[email protected]>
wasmDualFilterWithCodecsTestMatrix(bool include_nullvm, bool cpp_only, | ||
std::vector<Http::CodecType> codecs_type) { | ||
std::vector<std::tuple<std::string, std::string, bool, Http::CodecType>> values; | ||
for (const auto& codec_type : codecs_type) { |
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.
explicit type is better than auto
except the type name is complex.
And you should use value semantics here rather than reference semantics for enum.
By the way, I think you could also use structured bindings in this helper function?
Signed-off-by: Juan Manuel Ollé <[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!
This is a bug fix of wasm and won't make thing worse anyway. So, will let it enter the 1.32 at the last minute. |
Commit Message: wasm: Add data buffering for chunks Additional Description: In HTTP/2 connections, the last chunk, which contains the end_of_stream flag, is not used to call the Wasm callback. This fix addresses the issue by dumping the data into the buffer before calling the Wasm callback, ensuring that the data is now present. Risk Level: Low Testing: yes Docs Changes: n/a Release Notes: yes Platform Specific Features: n/a Fixes envoyproxy#35884 --------- Signed-off-by: Juan Manuel Ollé <[email protected]> Signed-off-by: Gustavo <[email protected]>
Commit Message: wasm: Add data buffering for chunks
Additional Description:
In HTTP/2 connections, the last chunk, which contains the end_of_stream flag, is not used to call the Wasm callback. This fix addresses the issue by dumping the data into the buffer before calling the Wasm callback, ensuring that the data is now present.
Risk Level: Low
Testing: yes
Docs Changes: n/a
Release Notes: yes
Platform Specific Features: n/a
Fixes #35884