-
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
grpc-json: Handle streaming backend error cases correctly #8323
grpc-json: Handle streaming backend error cases correctly #8323
Conversation
When a streaming backend returns an error in a trailer-only response, with the 'convert_grpc_status' option enabled, instead of writing the [] (empty array) in reply-body transcode the error in the headers and reply with {"code":...}. Risk Level: Low Testing: added an integraion test, tested manually. Documentation: n/a Release notes: n/a Fixes envoyproxy#8315 Signed-off-by: Anatoly Scheglov <ascheglov@yandex-team.ru>
On second thought, this could be improved. |
…s not Signed-off-by: Anatoly Scheglov <ascheglov@yandex-team.ru>
// If there was no previous headers frame, this |trailers| map is our |response_headers_|, | ||
// so there is no need to copy headers from one to the other. | ||
bool is_trailers_only_response = response_headers_ == &trailers; | ||
|
||
const absl::optional<Grpc::Status::GrpcStatus> grpc_status = | ||
Grpc::Common::getGrpcStatus(trailers); | ||
bool status_converted_to_json = grpc_status && maybeConvertGrpcStatus(*grpc_status, trailers); | ||
if (status_converted_to_json) { |
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 code is very hard to follow with so many if-else. Can we split them into two functions, one handling all logic of convert_to_json=true case, and another handling false case. Not need to worry about sharing code between them.
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.
Done, moved all the gRPC-status-to-JSON code into a separate function.
Signed-off-by: Anatoly Scheglov <ascheglov@yandex-team.ru>
@@ -592,8 +590,26 @@ bool JsonTranscoderFilter::maybeConvertGrpcStatus(Grpc::Status::GrpcStatus grpc_ | |||
return false; | |||
} | |||
|
|||
response_headers_->Status()->value(Grpc::Utility::grpcToHttpStatus(grpc_status)); | |||
|
|||
if (is_trailers_only_response) { |
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.
not need to have this if. non_trailer_only_response has been bailed out in line 560
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.
true, however I'm planning to remove that if (!is_trailers_only_response) return
in next PR, which would fix the http connection manager so that it would allow to add data from the encodeTrailers handler.
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.
does that mean you're going to handle status to json conversion in non trailers_only_response case?
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.
Yes, I'll remove this in #8404 .
We can transcode status into json as long as upstream doesn't send its own reply body.
That includes a single headers frame with the end_stream flag (i.e. trailers-only), and two headers frames (headers+trailers).
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.
Removed it.
// remove Trailer headers if the client connection was http/1 | ||
if (encoder_callbacks_->streamInfo().protocol() != Http::Protocol::Http2) { | ||
static const Http::LowerCaseString trailer_key = Http::LowerCaseString("trailer"); | ||
response_headers_->remove(trailer_key); |
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.
do we need to remove "trailer" header for non_json_converting case?
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.
yes, and it's already there, in encodeTrailers
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.
Great, thanks!
|
||
// remove Trailer headers if the client connection was http/1 | ||
if (encoder_callbacks_->streamInfo().protocol() != Http::Protocol::Http2) { | ||
static const Http::LowerCaseString trailer_key = Http::LowerCaseString("trailer"); |
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 know this were here before) since you're here, can you make this pointer or extract to a method with CONSTRUCT_ON_FIRST_USE, so doesn't cause static-initialization fiasco?
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.
done
#8312 was merged, could you ensure your changes still work as expected with the new tests? |
Signed-off-by: Anatoly Scheglov <ascheglov@yandex-team.ru>
I've checked it and there is no need to change anything. For streaming responses, the "content-type" header will be set twice, but that's alright because |
Apparently the asan build is stuck. How do I restart it? |
Push an empty commit: https://github.com/envoyproxy/envoy/blob/master/CONTRIBUTING.md#triggering-ci-re-run-without-making-changes |
Can you merge master? You commit doesn't contain asan job config in azp. |
/retest |
🤷♀️ nothing to rebuild. |
…#8323) When a streaming backend returns an error in a trailer-only response, with the 'convert_grpc_status' option enabled, instead of writing the [] (empty array) in reply-body transcode the error in the headers and reply with {"code":...}. Risk Level: Low Testing: added an integraion test, tested manually. Documentation: n/a Release notes: n/a Fixes envoyproxy#8315 Signed-off-by: Anatoly Scheglov <ascheglov@yandex-team.ru>
…#8323) When a streaming backend returns an error in a trailer-only response, with the 'convert_grpc_status' option enabled, instead of writing the [] (empty array) in reply-body transcode the error in the headers and reply with {"code":...}. Risk Level: Low Testing: added an integraion test, tested manually. Documentation: n/a Release notes: n/a Fixes envoyproxy#8315 Signed-off-by: Anatoly Scheglov <ascheglov@yandex-team.ru>
When a streaming backend returns an error in a trailer-only response,
with the 'convert_grpc_status' option enabled,
instead of writing the [] (empty array) in reply-body
transcode the error in the headers and reply with {"code":...}.
Risk Level: Low
Testing: added an integraion test, tested manually.
Documentation: n/a
Release notes: n/a
Fixes #8315