diff --git a/litellm/passthrough/utils.py b/litellm/passthrough/utils.py index e419322dca6..df39b8fad48 100644 --- a/litellm/passthrough/utils.py +++ b/litellm/passthrough/utils.py @@ -18,6 +18,7 @@ _PASS_THROUGH_PROTECTED_HEADERS: Final[frozenset] = frozenset( "x-goog-api-key", "host", "content-length", + "accept-encoding", } ) @@ -69,6 +70,9 @@ class BasePassthroughUtils: # Header We Should NOT forward request_headers.pop("content-length", None) request_headers.pop("host", None) + # accept-encoding must stay client-negotiated: forwarding e.g. "br" when + # the brotli package is absent relays undecodable bytes to the caller + request_headers.pop("accept-encoding", None) custom_header_names: Final = {header_name.lower() for header_name in headers} for header_name in list(request_headers.keys()): diff --git a/tests/test_litellm/proxy/pass_through_endpoints/test_vertex_passthrough_load_balancing.py b/tests/test_litellm/proxy/pass_through_endpoints/test_vertex_passthrough_load_balancing.py index aaf1dad4910..8e973fc3771 100644 --- a/tests/test_litellm/proxy/pass_through_endpoints/test_vertex_passthrough_load_balancing.py +++ b/tests/test_litellm/proxy/pass_through_endpoints/test_vertex_passthrough_load_balancing.py @@ -568,6 +568,32 @@ def test_forward_headers_custom_wins_case_insensitive_over_request_authorization assert result["x-request-id"] == "req-123" +def test_forward_headers_never_forwards_client_accept_encoding(): + """ + The client's Accept-Encoding must not reach the upstream provider: the proxy's + HTTP client decodes the upstream body and advertises only encodings it can + decode. Forwarding e.g. "br" on an install without the brotli package makes + the proxy relay raw compressed bytes with the content-encoding header stripped + (garbled JSON for /v1/models and count_tokens through the Anthropic passthrough). + """ + from litellm.passthrough.utils import BasePassthroughUtils + + request_headers = { + "accept-encoding": "gzip, deflate, br, zstd", + "x-pass-accept-encoding": "br", + "x-request-id": "req-123", + } + + result = BasePassthroughUtils.forward_headers_from_request( + request_headers=request_headers, + headers={}, + forward_headers=True, + ) + + assert "accept-encoding" not in result + assert result["x-request-id"] == "req-123" + + @pytest.mark.asyncio async def test_vertex_passthrough_custom_model_name_replaced_in_url(): """