Skip to content

Commit 36c2883

Browse files
authored
(proxy perf) - only read request body 1 time per request (#7728)
* req body * fix linting
1 parent feee37e commit 36c2883

File tree

1 file changed

+37
-6
lines changed

1 file changed

+37
-6
lines changed

litellm/proxy/common_utils/http_parsing_utils.py

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,35 @@ async def _read_request_body(request: Optional[Request]) -> Dict:
2121
try:
2222
if request is None:
2323
return {}
24+
25+
# Check if we already read and parsed the body
26+
_cached_request_body: Optional[dict] = _safe_get_request_parsed_body(
27+
request=request
28+
)
29+
if _cached_request_body is not None:
30+
return _cached_request_body
31+
2432
_request_headers: dict = _safe_get_request_headers(request=request)
2533
content_type = _request_headers.get("content-type", "")
34+
2635
if "form" in content_type:
27-
return dict(await request.form())
36+
parsed_body = dict(await request.form())
2837
else:
2938
# Read the request body
3039
body = await request.body()
3140

3241
# Return empty dict if body is empty or None
3342
if not body:
34-
return {}
43+
parsed_body = {}
44+
parsed_body = orjson.loads(body)
3545

36-
# Attempt JSON parsing (safe for untrusted input)
37-
return orjson.loads(body)
46+
# Cache the parsed result
47+
_safe_set_request_parsed_body(request=request, parsed_body=parsed_body)
48+
return parsed_body
3849

3950
except (json.JSONDecodeError, orjson.JSONDecodeError):
40-
# Log detailed information for debugging
4151
verbose_proxy_logger.exception("Invalid JSON payload received.")
4252
return {}
43-
4453
except Exception as e:
4554
# Catch unexpected errors to avoid crashes
4655
verbose_proxy_logger.exception(
@@ -49,6 +58,28 @@ async def _read_request_body(request: Optional[Request]) -> Dict:
4958
return {}
5059

5160

61+
def _safe_get_request_parsed_body(request: Optional[Request]) -> Optional[dict]:
62+
if request is None:
63+
return None
64+
if hasattr(request, "state") and hasattr(request.state, "parsed_body"):
65+
return request.state.parsed_body
66+
return None
67+
68+
69+
def _safe_set_request_parsed_body(
70+
request: Optional[Request],
71+
parsed_body: dict,
72+
) -> None:
73+
try:
74+
if request is None:
75+
return
76+
request.state.parsed_body = parsed_body
77+
except Exception as e:
78+
verbose_proxy_logger.debug(
79+
"Unexpected error setting request parsed body - {}".format(e)
80+
)
81+
82+
5283
def _safe_get_request_headers(request: Optional[Request]) -> dict:
5384
"""
5485
[Non-Blocking] Safely get the request headers

0 commit comments

Comments
 (0)