Consume request body in middleware is problematic
See original GitHub issuefrom starlette.applications import Starlette
from starlette.requests import Request
from starlette.responses import PlainTextResponse
from starlette.middleware.base import BaseHTTPMiddleware
class SampleMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
_ = await request.form()
return await call_next(request)
app = Starlette()
@app.route('/test', methods=['POST'])
async def test(request):
_ = await request.form() # blocked, because middleware already consumed request body
return PlainTextResponse('Hello, world!')
app.add_middleware(SampleMiddleware)
$ uvicorn test:app --reload
$ curl -d "a=1" http://127.0.0.1:8000/test
# request is blocked
Issue Analytics
- State:
- Created 4 years ago
- Reactions:13
- Comments:32 (7 by maintainers)
Top Results From Across the Web
Get starlette request body in the middleware context
So the line body = await request.body() freezes all requests that have body and I have 504 from all of them. How can...
Read more >Consuming the request body — Quart 0.17.0 documentation
The body is sent after the request line and headers for both HTTP/1 and HTTP/2. This allows Quart to trigger the app's request...
Read more >FAQ — Falcon 3.1.1 documentation
If your request authentication/authorization is performed in a middleware component which rejects requests lacking authorization credentials by raising an ...
Read more >Common API mistakes and how to avoid them - LogRocket Blog
If within a request handler, the application throws an error, then the Express server may respond with a Content-Type: text/plain and a body...
Read more >API Reference - Express 4.x
A new body object containing the parsed data is populated on the request object after the middleware (i.e. req.body ), or an empty...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Coming from FastAPI issue referenced above.
@tomchristie I don’t understand the issue about consuming the request in a middleware, could you explain this point ? In fact, I have the need (which is current where I work) to log every requests received by my production server. Is there a better place than a middleware to do it and avoid duplicating code in every endpoint ? (I would like something like this https://github.com/Rhumbix/django-request-logging)
For now, I found this workaround (but that’s not very pretty):
I kind of disagree with your example. In fact, stream data is not stored by default, but stream metadata (is the stream closed) are; there will be an understandable error raised if someone try to stream twice, and that is enough imho. That’s why if the body is cached, the stream consumption has to be cached too.
“Consume request body in middleware is problematic”
Indeed. Consuming request data in middleware is problematic. Not just to Starlette, but generally, everywhere.
On the whole you should avoid doing so if at all possible.
There’s some work we could do to make it work better, but there will always be cases where it can’t work (eg. if you stream the request data, then it’s just not going to be available anymore later down the line).