任务
我想编写将数据添加到最终响应的中间件。也就是说,这个答案:
{
"user": ...,
"some_field": ...
}
它应该变成这样:
{
"some_additional_field": ...,
"data": {
"user": ...,
"some_field": ...
}
}
为此我编写了中间件:
class ResponseFormatterMiddleware:
async def _post_process_response(self, response: Response) -> Response:
response.body = response.render({
"some_additional_field": 123,
"data": response.body
})
return response
async def __call__(self, request: Request, call_next) -> Response:
response = await call_next(request)
return await self._post_process_response(response)
并添加它:
app.middleware("http")(ResponseFormatterMiddleware())
但我收到一个错误:
AttributeError: '_StreamingResponse' object has no attribute 'body'
之后我发现我收到的输入不是fastapi.Request
, but starlette.middleware.base._CachedRequest
,但是执行控制器后我收到的输入不是fastapi.Response
, but starlette.middleware.base._StreamingResponse
。
问题)
是否可以像 django 中那样做 +- ?也就是说,使用中间件将附加信息写入请求中,然后以某种方式更改最终响应。
是否有可能以某种方式使用对象fastapi
而不是starlette
中间件?
我在网上找到了几种解决方案:
解决方案1:迎头赶上
您可以使用简单的表达式获取响应数据:
基于此,我做了以下示例:
缺点:
_StreamingResponse
执行中间件后最终(新)对象仍然会变成解决方案 2:自动装饰器或
route_class
https://stackoverflow.com/questions/64115628/get-starlette-request-body-in-the-middleware-context。
当然,这不是中间件,但它解决了问题。
fastapi.APIRouter
您可以为(来自该路由器要使用的route_class
文档自定义路由(路径操作)类)指定一个参数。它必须继承自
fastapi.routing.APIRoute
. 该方法get_route_handler
可用于替换最终处理程序,即创建一个将应用于给定路由器的所有端点的装饰器。这是源代码中稍微修改过的示例: