FastAPI中间件窥探响应 [英] FastAPI middleware peeking into responses
问题描述
我尝试编写一个简单的中间件,用于FastAPI窥探响应主体.
I try to write a simple middleware for FastAPI peeking into response bodies.
在此示例中,我只记录了正文内容:
In this example I just log the body content:
app = FastAPI()
@app.middleware("http")
async def log_request(request, call_next):
logger.info(f'{request.method} {request.url}')
response = await call_next(request)
logger.info(f'Status code: {response.status_code}')
async for line in response.body_iterator:
logger.info(f' {line}')
return response
但是看起来我是这样消耗"身体的,导致了此异常:
However it looks like I "consume" the body this way, resulting in this exception:
...
File ".../python3.7/site-packages/starlette/middleware/base.py", line 26, in __call__
await response(scope, receive, send)
File ".../python3.7/site-packages/starlette/responses.py", line 201, in __call__
await send({"type": "http.response.body", "body": b"", "more_body": False})
File ".../python3.7/site-packages/starlette/middleware/errors.py", line 156, in _send
await send(message)
File ".../python3.7/site-packages/uvicorn/protocols/http/httptools_impl.py", line 515, in send
raise RuntimeError("Response content shorter than Content-Length")
RuntimeError: Response content shorter than Content-Length
尝试查看响应对象,我看不到其他任何方式来读取其内容.正确的方法是什么?
Trying to look into the response object I couldn't see any other way to read its content. What is the correct way to do it?
推荐答案
我在FastAPI中间件中也有类似的需求,尽管不理想,但这是我们最终得到的东西:
I had a similar need in a FastAPI middleware and although not ideal here's what we ended up with:
app = FastAPI()
@app.middleware("http")
async def log_request(request, call_next):
logger.info(f'{request.method} {request.url}')
response = await call_next(request)
logger.info(f'Status code: {response.status_code}')
body = b""
async for chunk in response.body_iterator:
body += chunk
# do something with body ...
return Response(
content=body,
status_code=response.status_code,
headers=dict(response.headers),
media_type=response.media_type
)
请注意,这样的实现会在响应流式传输的内容不适合您服务器RAM的情况下出现问题(想象响应为100GB).
Be warned that such an implementation is problematic with responses streaming a body that would not fit in your server RAM (imagine a response of 100GB).
根据应用程序的功能,您将确定是否存在问题.
Depending on what your application does, you will rule if it is an issue or not.
在某些端点产生较大响应的情况下,您可能希望避免使用中间件,而是实现自定义ApiRoute.这种自定义的ApiRoute在消耗主体方面会遇到相同的问题,但是您可以将其用法限制为特定的端点.
In the case where some of your endpoints produce large responses, you might want to avoid using a middleware and instead implement a custom ApiRoute. This custom ApiRoute would have the same issue with consuming the body, but you can limit it's usage to a particular endpoints.
请访问> https://fastapi.tiangolo.com/advanced/custom-request-and-route/
这篇关于FastAPI中间件窥探响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!