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

grpc-json: Handle streaming backend error cases correctly #8323

Merged
merged 8 commits into from
Oct 3, 2019

Conversation

ascheglov
Copy link
Contributor

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

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>
@ascheglov
Copy link
Contributor Author

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) {
Copy link
Contributor

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.

Copy link
Contributor Author

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.

qiwzhang
qiwzhang previously approved these changes Sep 23, 2019
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) {
Copy link
Contributor

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

Copy link
Contributor Author

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.

Copy link
Member

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?

Copy link
Contributor Author

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

Copy link
Contributor Author

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);
Copy link
Contributor

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?

Copy link
Contributor Author

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

qiwzhang
qiwzhang previously approved these changes Sep 24, 2019
Copy link
Member

@lizan lizan left a 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");
Copy link
Member

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@nareddyt
Copy link
Contributor

#8312 was merged, could you ensure your changes still work as expected with the new tests?

Anatoly Scheglov added 2 commits September 25, 2019 12:42
Signed-off-by: Anatoly Scheglov <ascheglov@yandex-team.ru>
@ascheglov
Copy link
Contributor Author

#8312 was merged, could you ensure your changes still work as expected with the new tests?

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 setReference is cheap.

@ascheglov
Copy link
Contributor Author

Apparently the asan build is stuck. How do I restart it?

@nareddyt
Copy link
Contributor

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

@lizan
Copy link
Member

lizan commented Sep 27, 2019

Can you merge master? You commit doesn't contain asan job config in azp.

@ascheglov
Copy link
Contributor Author

/retest

@repokitteh-read-only
Copy link

🤷‍♀️ nothing to rebuild.

🐱

Caused by: a #8323 (comment) was created by @ascheglov.

see: more, trace.

Anatoly Scheglov added 2 commits September 27, 2019 15:48
Signed-off-by: Anatoly Scheglov <ascheglov@yandex-team.ru>
@ascheglov ascheglov requested review from lizan and qiwzhang October 2, 2019 09:38
@lizan lizan merged commit 492e5f7 into envoyproxy:master Oct 3, 2019
danzh2010 pushed a commit to danzh2010/envoy that referenced this pull request Oct 4, 2019
…#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>
nandu-vinodan pushed a commit to nandu-vinodan/envoy that referenced this pull request Oct 17, 2019
…#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>
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.

grpc-json: Handle streaming backend error cases correctly
4 participants