From dd64c2cc89577fb3fe666f51274375c6df0aa5bc Mon Sep 17 00:00:00 2001 From: Kushaan koul Date: Sat, 5 Sep 2026 16:27:19 +0530 Subject: [PATCH] feat(proxy): support suppressing x-litellm-version header (#39113) --- litellm/__init__.py | 1 + litellm/proxy/common_request_processing.py | 8 +++ .../proxy/test_common_request_processing.py | 58 +++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/litellm/__init__.py b/litellm/__init__.py index 41a3789ab0d..89960583651 100644 --- a/litellm/__init__.py +++ b/litellm/__init__.py @@ -429,6 +429,7 @@ autorouter_presets_url: str = os.getenv( "https://raw.githubusercontent.com/BerriAI/litellm/main/litellm/proxy/public_endpoints/autorouter_presets.json", ) suppress_debug_info: bool = False +suppress_version_header: bool = False dynamodb_table_name: Optional[str] = None s3_callback_params: Optional[Dict] = None s3_audit_callback_params: Optional[Dict] = None diff --git a/litellm/proxy/common_request_processing.py b/litellm/proxy/common_request_processing.py index fc83c1ddeed..ec7581e6f40 100644 --- a/litellm/proxy/common_request_processing.py +++ b/litellm/proxy/common_request_processing.py @@ -1,3 +1,4 @@ +import os import asyncio import contextlib import json @@ -1547,6 +1548,13 @@ class ProxyBaseLLMRequestProcessing: ) -> dict: exclude_values: Final = {"", None, "None"} hidden_params = hidden_params or {} + + if ( + getattr(litellm, "suppress_version_header", False) + or os.environ.get("LITELLM_SUPPRESS_VERSION_HEADER", "").lower() in ("true", "1") + or kwargs.pop("suppress_version_header", False) + ): + version = None timing_values: Final = _timing_values( hidden_params=hidden_params, logging_obj=litellm_logging_obj, diff --git a/tests/test_litellm/proxy/test_common_request_processing.py b/tests/test_litellm/proxy/test_common_request_processing.py index 6d6aad22ca3..5de3ec2aea2 100644 --- a/tests/test_litellm/proxy/test_common_request_processing.py +++ b/tests/test_litellm/proxy/test_common_request_processing.py @@ -544,6 +544,64 @@ class TestProxyBaseLLMRequestProcessing: assert headers["x-ratelimit-remaining-requests"] == "999" proxy_logging_obj.post_call_response_headers_hook.assert_awaited_once() + @pytest.mark.asyncio + async def test_build_litellm_proxy_success_headers_suppress_version(self): + """Test suppressing x-litellm-version header via global and env config.""" + import litellm + + mock_request = MagicMock() + mock_request.headers = {} + + class _FakeGenaiResponse: + _hidden_params = { + "model_id": "deployment-model-id", + "cache_key": "ck-test", + "api_base": "https://generativelanguage.googleapis.com/v1beta", + "response_cost": 0.001, + } + + mock_user = MagicMock() + mock_user.spend = 0.0 + mock_user.tpm_limit = None + mock_user.rpm_limit = None + mock_user.max_budget = None + mock_user.allowed_model_region = None + + logging_obj = MagicMock() + logging_obj.litellm_call_id = "call-id-test" + logging_obj.model_id = "deployment-model-id" + logging_obj.model_call_details = {"litellm_call_id": "call-id-test"} + + proxy_logging_obj = MagicMock() + proxy_logging_obj.post_call_response_headers_hook = AsyncMock() + + try: + litellm.suppress_version_header = True + headers = await ProxyBaseLLMRequestProcessing.build_litellm_proxy_success_headers_from_llm_response( + response=_FakeGenaiResponse(), + request_data={"model": "gemini/gemini-1.5-flash"}, + request=mock_request, + user_api_key_dict=mock_user, + logging_obj=logging_obj, + version="9.9.9", + proxy_logging_obj=proxy_logging_obj, + ) + assert "x-litellm-version" not in headers + finally: + litellm.suppress_version_header = False + + headers_kw = await ProxyBaseLLMRequestProcessing.build_litellm_proxy_success_headers_from_llm_response( + response=_FakeGenaiResponse(), + request_data={"model": "gemini/gemini-1.5-flash"}, + request=mock_request, + user_api_key_dict=mock_user, + logging_obj=logging_obj, + version="9.9.9", + proxy_logging_obj=proxy_logging_obj, + suppress_version_header=True, + ) + assert "x-litellm-version" not in headers_kw + @pytest.mark.asyncio async def test_build_litellm_proxy_success_headers_streaming_style_iterator(self): """AsyncGoogleGenAIGenerateContentStreamingIterator sets _hidden_params at init; headers must propagate."""