perf: use cached _safe_get_request_headers instead of dict(request.headers)

Replace 15 call sites across 9 files that called dict(request.headers)
with _safe_get_request_headers(request) which caches the result on
request.state. Mutation sites use .copy() to protect the shared cache.
This commit is contained in:
Ryan Crabbe
2026-02-17 16:11:50 -08:00
parent 3cc032bc0c
commit 7a2c889ec2
8 changed files with 24 additions and 15 deletions
@@ -10,6 +10,7 @@ from litellm.proxy._experimental.mcp_server.ui_session_utils import (
)
from litellm.proxy._experimental.mcp_server.utils import merge_mcp_headers
from litellm.proxy._types import UserAPIKeyAuth
from litellm.proxy.common_utils.http_parsing_utils import _safe_get_request_headers
from litellm.proxy.auth.ip_address_utils import IPAddressUtils
from litellm.proxy.auth.user_api_key_auth import user_api_key_auth
from litellm.types.mcp import MCPAuth
@@ -645,7 +646,7 @@ if MCP_AVAILABLE:
return await _execute_with_mcp_client(
new_mcp_server_request,
_test_connection_operation,
raw_headers=dict(request.headers),
raw_headers=_safe_get_request_headers(request),
)
@router.post("/test/tools/list")
@@ -700,5 +701,5 @@ if MCP_AVAILABLE:
_list_tools_operation,
mcp_auth_header=mcp_auth_header,
oauth2_headers=oauth2_headers,
raw_headers=dict(request.headers),
raw_headers=_safe_get_request_headers(request),
)
+1 -1
View File
@@ -559,7 +559,7 @@ async def _user_api_key_auth_builder( # noqa: PLR0915
user_api_key_cache=user_api_key_cache,
proxy_logging_obj=proxy_logging_obj,
parent_otel_span=parent_otel_span,
request_headers=dict(request.headers),
request_headers=_safe_get_request_headers(request),
)
is_proxy_admin = result["is_proxy_admin"]
@@ -3,6 +3,7 @@ from fastapi_sso.sso.base import OpenID
from litellm._logging import verbose_logger
from litellm.integrations.custom_logger import CustomLogger
from litellm.proxy.common_utils.http_parsing_utils import _safe_get_request_headers
class CustomSSOLoginHandler(CustomLogger):
@@ -18,7 +19,7 @@ class CustomSSOLoginHandler(CustomLogger):
self,
request: Request,
) -> OpenID:
request_headers_dict = dict(request.headers)
request_headers_dict = _safe_get_request_headers(request)
verbose_logger.debug("inside custom ui sso sign in hook...")
return OpenID(
id=request_headers_dict.get("x-litellm-user-id") or "123",
@@ -21,6 +21,7 @@ from typing_extensions import TypedDict
import litellm
from litellm._logging import verbose_proxy_logger
from litellm.proxy.common_utils.http_parsing_utils import _safe_get_request_headers
from litellm._uuid import uuid
from litellm.litellm_core_utils.safe_json_dumps import safe_dumps
from litellm.proxy._types import (
@@ -724,7 +725,7 @@ async def get_service_provider_config(request: Request):
"SCIM ServiceProviderConfig request: method=%s url=%s headers=%s",
request.method,
request.url,
dict(request.headers),
_safe_get_request_headers(request),
)
meta = {
"resourceType": "ServiceProviderConfig",
@@ -28,6 +28,7 @@ from litellm.proxy.auth.route_checks import RouteChecks
from litellm.proxy.auth.user_api_key_auth import user_api_key_auth
from litellm.proxy.common_utils.http_parsing_utils import (
_read_request_body,
_safe_get_request_headers,
_safe_set_request_parsed_body,
get_form_data,
get_request_body,
@@ -60,7 +61,7 @@ def create_request_copy(request: Request):
return {
"method": request.method,
"url": str(request.url),
"headers": dict(request.headers),
"headers": _safe_get_request_headers(request),
"cookies": request.cookies,
"query_params": dict(request.query_params),
}
@@ -329,7 +330,7 @@ async def vllm_proxy_route(
method=request.method,
endpoint=endpoint,
request_query_params=request.query_params,
request_headers=dict(request.headers),
request_headers=_safe_get_request_headers(request),
stream=request_body.get("stream", False),
content=None,
data=None,
@@ -1307,7 +1308,7 @@ async def azure_proxy_route(
method=request.method,
endpoint=endpoint,
request_query_params=request.query_params,
request_headers=dict(request.headers),
request_headers=_safe_get_request_headers(request),
stream=request_body.get("stream", False),
content=None,
data=None,
@@ -1505,7 +1506,7 @@ def get_vertex_ai_allowed_incoming_headers(request: Request) -> dict:
Returns:
dict: Headers dictionary with only allowed headers
"""
incoming_headers = dict(request.headers) or {}
incoming_headers = _safe_get_request_headers(request)
headers = {}
for header_name in ALLOWED_VERTEX_AI_PASSTHROUGH_HEADERS:
if header_name in incoming_headers:
@@ -1621,7 +1622,7 @@ async def _prepare_vertex_auth_headers(
if (
vertex_credentials is None or vertex_credentials.vertex_project is None
) and router_credentials is None:
headers = dict(request.headers) or {}
headers = _safe_get_request_headers(request).copy()
headers_passed_through = True
verbose_proxy_logger.debug(
"default_vertex_config not set, incoming request headers %s", headers
@@ -50,7 +50,10 @@ from litellm.proxy._types import (
)
from litellm.proxy.auth.user_api_key_auth import user_api_key_auth
from litellm.proxy.common_request_processing import ProxyBaseLLMRequestProcessing
from litellm.proxy.common_utils.http_parsing_utils import _read_request_body
from litellm.proxy.common_utils.http_parsing_utils import (
_read_request_body,
_safe_get_request_headers,
)
from litellm.proxy.utils import get_server_root_path
from litellm.secret_managers.main import get_secret_str
from litellm.types.llms.custom_http import httpxSpecialProvider
@@ -644,7 +647,7 @@ async def pass_through_request( # noqa: PLR0915
url = httpx.URL(target)
headers = custom_headers
headers = HttpPassThroughEndpointHelpers.forward_headers_from_request(
request_headers=dict(request.headers),
request_headers=_safe_get_request_headers(request).copy(),
headers=headers,
forward_headers=forward_headers,
)
+3 -2
View File
@@ -292,6 +292,7 @@ from litellm.proxy.common_utils.encrypt_decrypt_utils import (
from litellm.proxy.common_utils.html_forms.ui_login import build_ui_login_form
from litellm.proxy.common_utils.http_parsing_utils import (
_read_request_body,
_safe_get_request_headers,
check_file_size_under_limit,
get_form_data,
)
@@ -10167,7 +10168,7 @@ async def async_queue_request(
data["proxy_server_request"] = {
"url": str(request.url),
"method": request.method,
"headers": dict(request.headers),
"headers": _safe_get_request_headers(request),
"body": copy.copy(data), # use copy instead of deepcopy
}
@@ -10188,7 +10189,7 @@ async def async_queue_request(
data["metadata"] = {}
data["metadata"]["user_api_key"] = user_api_key_dict.api_key
data["metadata"]["user_api_key_metadata"] = user_api_key_dict.metadata
_headers = dict(request.headers)
_headers = _safe_get_request_headers(request).copy()
_headers.pop(
"authorization", None
) # do not store the original `sk-..` api key in the db
@@ -19,6 +19,7 @@ from fastapi import APIRouter, Request, Response
import litellm
from litellm.proxy._types import *
from litellm.proxy.auth.user_api_key_auth import user_api_key_auth
from litellm.proxy.common_utils.http_parsing_utils import _safe_get_request_headers
from litellm.proxy.litellm_pre_call_utils import _get_dynamic_logging_metadata
from litellm.proxy.pass_through_endpoints.pass_through_endpoints import (
create_pass_through_route,
@@ -32,7 +33,7 @@ def create_request_copy(request: Request):
return {
"method": request.method,
"url": str(request.url),
"headers": dict(request.headers),
"headers": _safe_get_request_headers(request),
"cookies": request.cookies,
"query_params": dict(request.query_params),
}