在aiohttp中是否有类似于flask中的请求后方法



Flask提供了这个不错的@app.after_request装饰器,它允许在处理http请求后执行方法。请参阅此处的文档。

您将如何使用aiohttp实现类似的模式?通常在处理请求后发送日志。

aiohttpweb服务器支持信号,这些信号是在特定点调用的挂钩。

Application.on_response_prepare信号在道义上等同于Flask的after_request处理器。在准备返回给客户端时,使用它来修改响应:

async def on_prepare(request, response):
response.headers['My-Header'] = 'value'
app.on_response_prepare.append(on_prepare)

该信号同时接收requestresponse对象。如果您想实现Flask模式来注册每个请求的回调,并且正在使用Python 3.7,则可以使用contextvars上下文变量:

from contextvars import ContextVar
from typing import Iterable, Callable
from aiohttp import web

PrepareCallback = Callable[[web.Request, web.StreamResponse], None]
call_on_prepare: ContextVar[Iterable[PrepareCallback]] = ContextVar('call_on_prepare', ())

async def per_request_callbacks(request, response):
# executed sequentially, in order of registration!
for callback in call_on_prepare.get():
await callback(request, response)

app.on_response_prepare.append(per_request_callbacks)

def response_prepare_after_this_request(awaitable):
call_on_prepare.set(call_on_prepare.get() + (awaitable,))
return awaitable

然后在请求中这样使用:

def invalidate_username_cache():
@response_prepare_after_this_request
async def delete_username_cookie(request, response):
response.del_cookie('username')
return response

如果您需要支持Python版本<3.7,则必须将回调列表存储在apprequestresponse对象上;请参阅aiohttp常见问题解答的数据共享部分。就我个人而言,我认为contextvars是更好的模式,因为这为response_prepare_after_this_request这样的实用程序提供了更好的封装,现在可以单独分发,而不用担心与aiohttp.web对象映射中的其他数据集发生冲突。

最新更新