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
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Trusting the Content-Length header alone is unsafe; you must also count the bytes you actually read.
- 2Consuming request.stream() drains it, so you must replace request._receive to let downstream handlers read the body again.
- 3Returning a Response from dispatch short-circuits the request before it ever reaches the route.
Related explainers
python
from pathlib import Path from collections import defaultdict from PIL import Image
Finding near-duplicate images by perceptual hash
perceptual-hashing
clustering
hamming-distance
Intermediate
9 steps
java
@Controller @RequestMapping("/employees") public class EmployeeController {
Customizing form binding in a Spring MVC controller
data-binding
validation
type-conversion
Intermediate
9 steps
go
package admin import ( "net/http"
Building a protected admin area in Gin
routing
middleware
authentication
Intermediate
6 steps
python
import logging import uuid from contextvars import ContextVar
Request ID tracing in FastAPI middleware
middleware
context-variables
request-tracing
Intermediate
7 steps
javascript
const express = require('express'); const EventEmitter = require('events'); const router = express.Router();
Server-Sent Events with Express
server-sent-events
streaming
event-emitter
Advanced
8 steps
go
package middleware import ( "errors"
Capping request body size in Gin
middleware
request limits
error handling
Intermediate
5 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/enforcing-a-max-request-body-size-in-fastapi-explained-python-2ae8/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.