fix(codec): respect server's enabled encodings when selecting response compression#2655
Open
kv-cache wants to merge 1 commit into
Open
fix(codec): respect server's enabled encodings when selecting response compression#2655kv-cache wants to merge 1 commit into
kv-cache wants to merge 1 commit into
Conversation
|
|
…e compression `CompressionEncoding::from_accept_encoding_header` picks an encoding from the client's `grpc-accept-encoding` header gated only on `cfg(feature = ...)`, not on whether the server actually enabled that encoding via `.send_compressed(...)`. A server configured for Zstd would gzip every response whenever a client listed `gzip` before `zstd` in `grpc-accept-encoding` -- even though the server never asked for gzip and would not have advertised it in `into_accept_encoding_header_value`. The sibling `from_encoding_header` already guards each match arm on `enabled_encodings.is_enabled(...)`; this fix brings the accept-side in line. Observed in production: tonic 0.14.6 server set to `send_compressed(Zstd)` only, clients sending `gzip,zstd,identity`, ~38% of server CPU spent in `miniz_oxide::deflate`. Adds three unit tests covering: * server-only-Zstd, client lists gzip first -> picks Zstd * no overlap between server and client lists -> picks None * both enabled, client prefers gzip -> picks Gzip
396063a to
155107d
Compare
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.
Motivation
CompressionEncoding::from_accept_encoding_headerselects a response compression encoding based purely on the client'sgrpc-accept-encodingheader and the compile-time feature set, not the runtime set of encodings the server enabled viaServer::send_compressed(...).When the server has only zstd enabled but the client advertises
gzip,zstd,identity, tonic compresses the response with gzip, which is an encoding the server never opted into and would not have advertised back.The sibling
from_encoding_header(used for request decompression) already has the correctif enabled_encodings.is_enabled(...)guards per match arm. This PR brings the accept-side in line.Observed in production with tonic 0.14.6: server configured
send_compressed(Zstd)only, ~38% of server CPU inminiz_oxide::deflate. Worked around downstream with a tower layer that rewrites the incominggrpc-accept-encodingheader to"zstd,identity"to force the buggy selection onto the correct path. After the fix, that work-around will no longer be needed.The bug affects all four RPC kinds —
from_accept_encoding_headeris called fromunary/server_streaming/client_streaming/streamingintonic/src/server/grpc.rs.Solution
Add a runtime
is_enabledguard to each match arm offrom_accept_encoding_headerso the function returns the first encoding in the intersection of (server-enabled, client-accepted), preserving the client's preference order. ReturnsNoneif the intersection is empty so the server falls back to identity-encoded responses.Adds three unit tests in
mod testsoftonic/src/codec/compression.rs:grpc-accept-encodingfrom_accept_encoding_header_respects_server_enabled_encodingsZstdgzip,zstd,identitySome(Zstd)from_accept_encoding_header_returns_none_when_no_overlapZstdgzip,identityNonefrom_accept_encoding_header_uses_client_preference_orderZstd,Gzipgzip,zstd,identitySome(Gzip)All three unit tests fail on master without the code fix; all pass with it. Existing
tonicunit tests (79) andcompressionintegration tests (63) continue to pass.Backport note
This fix applies cleanly. Flagging that the
v0.14.xbranch head appears to be behind thetonic-v0.14.6tag (latest commit there ischore: prepare v0.14.5 release), so I targeted master like v0.14.6 did. Happy to open a parallel PR againstv0.14.xif maintainers want a backport.