Skip to content

grpc json transcoder: Support response_body#10892

Merged
mattklein123 merged 16 commits into
envoyproxy:masterfrom
euroelessar:response-body
Jul 14, 2020
Merged

grpc json transcoder: Support response_body#10892
mattklein123 merged 16 commits into
envoyproxy:masterfrom
euroelessar:response-body

Conversation

@euroelessar
Copy link
Copy Markdown
Contributor

@euroelessar euroelessar commented Apr 22, 2020

Description: Add support for google.api.Http.response_body field.
Risk Level: medium (new parsing of potentially untrusted user data, but requires config change to be active)
Testing: added unit test
Docs Changes: n/a (body/response_body are part of google api documentation and are not mentioned in envoy docs)
Release Notes: added
Fixes #10870

Signed-off-by: Ruslan Nigmatullin <elessar@dropbox.com>
@euroelessar euroelessar requested a review from lizan as a code owner April 22, 2020 02:53
} else if (tag == 0) {
return true;
} else {
if (!Protobuf::internal::WireFormatLite::SkipField(input, tag)) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Dependency on internal API worries me, but I didn't find a better way without actually copying the same logic.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Comment on lines +700 to +701
// TODO(elessar): Return error to client.
encoder_callbacks_->resetStream();
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Is there a way to actually return 500 http status code to client right here if first message is invalid and stop fetching bad body from the upstream?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

you can call encoder_callbackds_->sendLocalReply() to return 500.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

sendLocalReply is only available as part of decoder_callbacks_, at encoding phase it's too late to call it.

Copy link
Copy Markdown
Member

@lizan lizan Apr 27, 2020

Choose a reason for hiding this comment

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

Yes it is usually too late at encodeData, unless you returned StopIteration in encodeHeaders, then you can modify headers and Continue. (which is the case here)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Is there a way to indicate envoy that there will be no more data (end_stream=true)?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yes, end_stream = true means not more data.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

seems no, we have StopIterationAndEndStream in FilterHeaderStatus but not in data. cc @mattklein123?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yeah I think this is a new use case we haven't hit before. You might be able to hack something up with injectEncodedDataToFilterChain (0 bytes + end_stream), but otherwise I think this would require HCM changes. cc @alyssawilk @snowp to see if I am forgetting about something.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ooh error handling on the response path!

AFIK the only example we have of this is in the HCM responseDataTooLarge.
In theory once we've stared running responses through the filter chain, we can't run them again (i.e. if headers are blocked by some downstream filter and haven't been written to the client, we can send a 500 but e can't send headers through the filter chain a second time)

I think the same way that we have a sendLocalReply for decoder filter callbacks we could have a sendReplyOrResetStream() for encoder filter callbacks which factors out the HCM responseDataTooLarge logic and either ships headers + body directly to the codec, or resets the stream.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think the same way that we have a sendLocalReply for decoder filter callbacks we could have a sendReplyOrResetStream() for encoder filter callbacks which factors out the HCM responseDataTooLarge logic and either ships headers + body directly to the codec, or resets the stream.

Yeah +1. I would probably just submit this PR the way you have it now with a TODO and then circle back with an HCM change if you so desire.

http_body.Clear();
Buffer::ZeroCopyInputStreamImpl stream(std::move(frame.data_));
http_body.ParseFromZeroCopyStream(&stream);
if (!HttpBodyUtils::parseMessageByFieldPath(&stream, method_->response_body_field_path,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Doing there is only supporting HttpBody response. What about normal JSON response?

You may have to implement it here

https://github.com/grpc-ecosystem/grpc-httpjson-transcoding/blob/master/src/response_to_json_translator.cc#L57

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I can submit a version of this change to grpc-httpjson-transcoding library instead & use it both here for HttpBody and there for JSON.
Protobuf spec allows inclusion of the same message field multiple times with an expectation that parser merges them. In order to support this generically I may need to provide ZeroCopyInputStream implementation built on top of the chain of sub-streams. It can be somehow less efficient though hopefully still the same amount of copies.

Thoughts?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Alternatively we could decide to not support this edge case and treat it as an error until somebody complains.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We can make supporting response_body in HttpBody and JSON as two different features. This PR can be just for HttpBody, and file another issue to track JSON feature.

Please log a proper warning or error code for not supported case.

Signed-off-by: Ruslan Nigmatullin <elessar@dropbox.com>
@stale
Copy link
Copy Markdown

stale Bot commented May 6, 2020

This pull request has been automatically marked as stale because it has not had activity in the last 7 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions!

@stale stale Bot added the stale stalebot believes this issue/PR has not been touched recently label May 6, 2020
Signed-off-by: Ruslan Nigmatullin <elessar@dropbox.com>
Signed-off-by: Ruslan Nigmatullin <elessar@dropbox.com>
@stale stale Bot removed the stale stalebot believes this issue/PR has not been touched recently label May 11, 2020
qiwzhang
qiwzhang previously approved these changes May 11, 2020
@stale
Copy link
Copy Markdown

stale Bot commented May 22, 2020

This pull request has been automatically marked as stale because it has not had activity in the last 7 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions!

@stale stale Bot added the stale stalebot believes this issue/PR has not been touched recently label May 22, 2020
@euroelessar
Copy link
Copy Markdown
Contributor Author

Still working on it, will update the CL by end of the week

@stale stale Bot removed the stale stalebot believes this issue/PR has not been touched recently label May 28, 2020
@stale
Copy link
Copy Markdown

stale Bot commented Jun 5, 2020

This pull request has been automatically marked as stale because it has not had activity in the last 7 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions!

@stale stale Bot added the stale stalebot believes this issue/PR has not been touched recently label Jun 5, 2020
Ruslan Nigmatullin added 2 commits June 11, 2020 18:25
Signed-off-by: Ruslan Nigmatullin <elessar@dropbox.com>
Signed-off-by: Ruslan Nigmatullin <elessar@dropbox.com>
@stale stale Bot removed the stale stalebot believes this issue/PR has not been touched recently label Jun 12, 2020
Ruslan Nigmatullin added 2 commits June 11, 2020 20:23
Signed-off-by: Ruslan Nigmatullin <elessar@dropbox.com>
Signed-off-by: Ruslan Nigmatullin <elessar@dropbox.com>
@stale
Copy link
Copy Markdown

stale Bot commented Jun 26, 2020

This pull request has been automatically marked as stale because it has not had activity in the last 7 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions!

@stale stale Bot added the stale stalebot believes this issue/PR has not been touched recently label Jun 26, 2020
Signed-off-by: Ruslan Nigmatullin <elessar@dropbox.com>
@stale stale Bot removed the stale stalebot believes this issue/PR has not been touched recently label Jul 2, 2020
@lizan
Copy link
Copy Markdown
Member

lizan commented Jul 6, 2020

@euroelessar the coverage fail is real due to lack of coverage.

/wait

Ruslan Nigmatullin added 3 commits July 9, 2020 01:32
Signed-off-by: Ruslan Nigmatullin <elessar@dropbox.com>
Signed-off-by: Ruslan Nigmatullin <elessar@dropbox.com>
Signed-off-by: Ruslan Nigmatullin <elessar@dropbox.com>
Signed-off-by: Ruslan Nigmatullin <elessar@dropbox.com>
@euroelessar
Copy link
Copy Markdown
Contributor Author

/retest

@repokitteh-read-only
Copy link
Copy Markdown

🤷‍♀️ nothing to rebuild.

🐱

Caused by: a #10892 (comment) was created by @euroelessar.

see: more, trace.

@euroelessar
Copy link
Copy Markdown
Contributor Author

/retest

@repokitteh-read-only
Copy link
Copy Markdown

🤷‍♀️ nothing to rebuild.

🐱

Caused by: a #10892 (comment) was created by @euroelessar.

see: more, trace.

Ruslan Nigmatullin added 2 commits July 9, 2020 16:30
Signed-off-by: Ruslan Nigmatullin <elessar@dropbox.com>
Signed-off-by: Ruslan Nigmatullin <elessar@dropbox.com>
@euroelessar
Copy link
Copy Markdown
Contributor Author

@lizan Thanks for the patience, I've fixed the coverage for the pieces introduced by this pull request.

@euroelessar
Copy link
Copy Markdown
Contributor Author

ASAN failure looks weird though, all tests are passed but:

2020-07-10T00:52:26.7829614Z INFO: Build completed successfully, 2422 total actions
2020-07-10T00:52:26.8069132Z $TEST_TMPDIR defined: output root default is '/build/tmp' and max_idle_secs default is '15'.
2020-07-10T00:52:26.8652399Z ls: cannot access '/tmp/tap//tap_*.pb_text': No such file or directory
2020-07-10T00:52:27.5476798Z 
2020-07-10T00:52:27.5557545Z ##[error]Bash exited with code '2'.
2020-07-10T00:52:27.5573440Z ##[section]Finishing: Run CI script

@dio
Copy link
Copy Markdown
Member

dio commented Jul 10, 2020

@euroelessar a fix from @lizan is on its way: #12018.

Signed-off-by: Ruslan Nigmatullin <elessar@dropbox.com>
@euroelessar
Copy link
Copy Markdown
Contributor Author

Failed coverage test is test/integration/load_stats_integration_test.cc, which looks like unrelated flake

@mattklein123 mattklein123 merged commit d7140cb into envoyproxy:master Jul 14, 2020
scheler pushed a commit to scheler/envoy that referenced this pull request Aug 4, 2020
Signed-off-by: Ruslan Nigmatullin <elessar@dropbox.com>
Signed-off-by: scheler <santosh.cheler@appdynamics.com>
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 transcoding: Support response_body annotation

6 participants