fix(grpc-web): response contains two trailer chunks#11988
Merged
juzhiyuan merged 6 commits intoapache:masterfrom Feb 25, 2025
Merged
fix(grpc-web): response contains two trailer chunks#11988juzhiyuan merged 6 commits intoapache:masterfrom
juzhiyuan merged 6 commits intoapache:masterfrom
Conversation
moonming
previously approved these changes
Feb 25, 2025
membphis
previously approved these changes
Feb 25, 2025
nic-6443
previously approved these changes
Feb 25, 2025
membphis
approved these changes
Feb 25, 2025
nic-6443
approved these changes
Feb 25, 2025
juzhiyuan
approved these changes
Feb 25, 2025
Member
juzhiyuan
left a comment
There was a problem hiding this comment.
I have reviewed the test cases, LGTM
|
|
||
| if encoding == CONTENT_ENCODING_BASE64 then | ||
| body = decode_base64(body) | ||
| ngx.log(ngx.WARN, "DECODE BODY: ", body) |
Contributor
There was a problem hiding this comment.
- why do we need warn log here?
- we can use core.log.warn instead
Contributor
Author
There was a problem hiding this comment.
Obviously here leaves out some unneeded code, which I will remove in another PR. 🫡
Contributor
Author
There was a problem hiding this comment.
This is probably code for testing and debugging.
| -- n bytes: trailer | ||
| trailer_buf = trailer_buf .. grpc_web_trailer | ||
|
|
||
| return trailer_buf |
Contributor
There was a problem hiding this comment.
Suggested change
| return trailer_buf | |
| return trailer_buf |
Contributor
There was a problem hiding this comment.
this is a good first issue, hopefully someone from the community can fix this.
5 tasks
shreemaan-abhishek
pushed a commit
to shreemaan-abhishek/apisix
that referenced
this pull request
Jan 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This PR is intended to address the following issues:
The reason for this is easy to explain, the old code used
statusto assert whether the response body had finished.But this is unreliable, and it can go wrong in the following cases:
Since the response is chunked, the trailer chunk from upstream may not be fully included in the first response block, so the upstream_trailer_grpc_message variable is not available in the first body_filter, which causes APISIX to trigger the body_filter call a second time and incorrectly add a duplicate trailer block.
Based on the pseudo-code above, you'll see that when this happens, the
upstream_trailer_grpc_statusvalue is already available to us at the firstbody_filtercall, which causes the plugin code to send a trailer chunk.When the next upstream chunk is received,
body_filteris called a second time, andupstream_trailer_grpc_statusstill has the value it had before, so the plugin code sends the trailer block again.This results in multiple duplicate trailers and accidentally breaks the grpc-web js client in the browser.
This PR changes the end of the response asserted using the
statusvalue to use thengx.arg[2]value, which will be the most reliable and trigger the code to send the trailer only on the last chunk.Checklist
The PR does have some compatibility changes, specifically:
405 Method not allowedinstead of400 Bad Request, which will be more semantic and have no effect on any official client.This has no effect on users who are already using the plugin correctly, so while it may introduce some behavioral changes, it is not a BREAK CHANGE.
In addition to that, I've noticed some behavior that doesn't quite fit the protocol reference implementation; as a grpc-web proxy, the HTTP trailer chunk should be removed and instead be represented as an encoded response body chunk, which APISIX fails to handle correctly. However, since browsers don't care about trailer chunks, this doesn't seem to cause an error, and I'll see how I can work around it and possibly fix it later.