python 45 lines · 6 steps

Enforcing a max request body size in FastAPI

A Starlette middleware that rejects oversized request bodies both by declared header and by actual bytes streamed.

Explained by highlit
1from starlette.middleware.base import BaseHTTPMiddleware
2from starlette.requests import Request
3from starlette.responses import JSONResponse, Response
4from starlette.status import HTTP_413_REQUEST_ENTITY_TOO_LARGE
5 
6 
7class MaxBodySizeMiddleware(BaseHTTPMiddleware):
8 def __init__(self, app, *, max_bytes: int = 1024 * 1024):
9 super().__init__(app)
10 self.max_bytes = max_bytes
11 
12 async def dispatch(self, request: Request, call_next) -> Response:
13 content_length = request.headers.get("content-length")
14 if content_length is not None:
15 try:
16 declared = int(content_length)
17 except ValueError:
18 return self._too_large()
19 if declared > self.max_bytes:
20 return self._too_large()
21 
22 received = 0
23 chunks: list[bytes] = []
24 async for chunk in request.stream():
25 received += len(chunk)
26 if received > self.max_bytes:
27 return self._too_large()
28 chunks.append(chunk)
29 
30 body = b"".join(chunks)
31 
32 async def receive():
33 return {"type": "http.request", "body": body, "more_body": False}
34 
35 request._receive = receive
36 return await call_next(request)
37 
38 def _too_large(self) -> JSONResponse:
39 return JSONResponse(
40 status_code=HTTP_413_REQUEST_ENTITY_TOO_LARGE,
41 content={
42 "detail": "Request body exceeds the maximum allowed size",
43 "max_bytes": self.max_bytes,
44 },
45 )
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Trusting the Content-Length header alone is unsafe; you must also count the bytes you actually read.
  2. 2Consuming request.stream() drains it, so you must replace request._receive to let downstream handlers read the body again.
  3. 3Returning a Response from dispatch short-circuits the request before it ever reaches the route.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Enforcing a max request body size in FastAPI — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code