Been trying to get the BODY of a request using FASTAPI middleware but it seems i can only get request.headers but not the body. I am in need of the body in order to get a key that I will use to check something on the database. Think of logging or authentication usage of a middleware.
@app.middleware("http")
async def TestCustomMiddleware(request: Request, call_next):
print("Middleware works!", request.headers)
response = await call_next(request)
resp_body = [section async for section in response.__dict__['body_iterator']]
print("BODY:", resp_body)
return response
I am able to get this but there is an error that will break the POST request:
INFO: Started server process [37160]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
Middleware works! Headers({'content-type': 'application/json', 'user-agent': 'PostmanRuntime/7.26.8', 'accept': '*/*', 'cache-control': 'no-cache', 'postman-token': 'ca6839ec-833d-45c0-9b52-8f904db13966', 'host': 'localhost:8000', 'accept-encoding': 'gzip, deflate, br', 'connection': 'keep-alive', 'content-length': '12'})
BODY: [b'{"test":"1"}']
INFO: 127.0.0.1:60761 - "POST /jctest HTTP/1.1" 200 OK
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "C:\Python\Python38\lib\site-packages\uvicorn\protocols\http\httptools_impl.py", line 386, in run_asgi
result = await app(self.scope, self.receive, self.send)
File "C:\Python\Python38\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 45, in __call__
return await self.app(scope, receive, send)
File "C:\Python\Python38\lib\site-packages\fastapi\applications.py", line 181, in __call__
await super().__call__(scope, receive, send)
File "C:\Python\Python38\lib\site-packages\starlette\applications.py", line 111, in __call__
await self.middleware_stack(scope, receive, send)
File "C:\Python\Python38\lib\site-packages\starlette\middleware\errors.py", line 181, in __call__
raise exc from None
File "C:\Python\Python38\lib\site-packages\starlette\middleware\errors.py", line 159, in __call__
await self.app(scope, receive, _send)
File "C:\Python\Python38\lib\site-packages\starlette\middleware\base.py", line 26, in __call__
await response(scope, receive, send)
File "C:\Python\Python38\lib\site-packages\starlette\responses.py", line 228, in __call__
await run_until_first_complete(
File "C:\Python\Python38\lib\site-packages\starlette\concurrency.py", line 18, in run_until_first_complete
[task.result() for task in done]
File "C:\Python\Python38\lib\site-packages\starlette\concurrency.py", line 18, in <listcomp>
[task.result() for task in done]
File "C:\Python\Python38\lib\site-packages\starlette\responses.py", line 225, in stream_response
await send({"type": "http.response.body", "body": b"", "more_body": False})
File "C:\Python\Python38\lib\site-packages\starlette\middleware\errors.py", line 156, in _send
await send(message)
File "C:\Python\Python38\lib\site-packages\uvicorn\protocols\http\httptools_impl.py", line 516, in send
raise RuntimeError("Response content shorter than Content-Length")
RuntimeError: Response content shorter than Content-Length
How can I fix this so I can get the body of the request which is {"test":"1"}
?
Trying get the body to find a key that will be used to check a database and either grant access to an API or deny it based on credentials.
5条答案
按热度按时间lhcgjxsq1#
You need to
await
on the request so the request object is infact ready to be read. This is how I achieved it.yqhsw0fo2#
Solution of getting request body references FastAPI - Custom APIRoute class in a router
f0brbegy3#
I would recommend using a router instead. Reference this github issue
Here is an example
vfh0ocws4#
在FASTAPI的中间件内部尝试
request.body()
或request.json()
将挂起。这是Starlette中的已知问题,记录如下,并提供了解决方法:https://github.com/tiangolo/fastapi/issues/394#issuecomment-883524819
inb24sb25#
Quoting FastAPI Doc about "Details about the Request object":
As FastAPI is actually Starlette underneath, with a layer of several tools on top, you can use Starlette's Request object directly when you need to.
And the starlette doc about the request body object says:
There are a few different interfaces for returning the body of the request:
Tested with curl: