From 06e59d252b2f9c5f78e0315b6ca098b7db6d5b59 Mon Sep 17 00:00:00 2001 From: Benoit Chesneau Date: Sat, 4 Apr 2026 02:27:57 +0200 Subject: [PATCH] Fix Litestar request handling - use raw ASGI receive for body/headers Litestar internally caches request.body() and request.headers which caused stale data to be returned on subsequent requests over keep-alive connections. Access body via receive callable and headers directly from scope to avoid this caching behavior. --- .../frameworks/litestar_app/app.py | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/tests/docker/asgi_framework_compat/frameworks/litestar_app/app.py b/tests/docker/asgi_framework_compat/frameworks/litestar_app/app.py index 9f0d49ee..322d5c28 100644 --- a/tests/docker/asgi_framework_compat/frameworks/litestar_app/app.py +++ b/tests/docker/asgi_framework_compat/frameworks/litestar_app/app.py @@ -83,15 +83,29 @@ async def scope_endpoint(request: Request) -> Dict[str, Any]: @post("/echo") async def echo(request: Request) -> Response: """Echo request body back.""" - body = await request.body() - content_type = request.headers.get("content-type", "application/octet-stream") + # Read body using the receive callable to avoid Litestar's internal caching + body_parts = [] + while True: + message = await request.receive() + body = message.get("body", b"") + if body: + body_parts.append(body) + if not message.get("more_body", False): + break + body = b"".join(body_parts) + # Access headers directly from scope to avoid Litestar's caching + scope_headers = {name.decode("latin-1"): value.decode("latin-1") + for name, value in request.scope.get("headers", [])} + content_type = scope_headers.get("content-type", "application/octet-stream") return Response(content=body, media_type=content_type, status_code=200) @get("/headers") async def headers_endpoint(request: Request) -> Dict[str, str]: """Return request headers as JSON.""" - return dict(request.headers) + # Access headers directly from scope to avoid Litestar's caching + scope_headers = request.scope.get("headers", []) + return {name.decode("latin-1"): value.decode("latin-1") for name, value in scope_headers} @get("/status/{code:int}")