我如何编写符合 ASGI 的中间件(同时保持与框架无关)?
How do I write an ASGI compliant middleware (while staying framework-agnostic)?
我们目前正在维护用多个 HTTP 框架(Flask、aiohttp 和 FastAPI)编写的代码。重写它们使它们都使用相同的框架目前是不可行的。我想在这些应用程序之间共享一些代码,它们非常适合中间件(日志配置、监控、身份验证……)。
最初的实现是通过子类化 Flask 完成的,并且在所有基于 Flask 的应用程序中都运行良好。但是在aiohttp或者FastAPI中是不可用的。
创建一个与框架无关的实现是可行的(理论上),今天早上我采用了一个更简单的案例并成功地将它转换为 WSGI 中间件并且能够将它集成到 Flask 应用程序中。
但是 ASGI 给我带来了一些麻烦,因为 纯 ASGI 中间件的文档不多。所有示例都显示了如何为 他们的 框架编写中间件。
official ASGI docs 在那个话题上也真的很“瘦”。据我所知,它应该看起来像这样(附带问题:“传递给构造函数的第二个参数是什么?”):
class MyMiddleware:
def __init__(self, app, something) -> None:
self.app = app
self.something = something # <- what is this second argument?
async def __call__(self, scope, receive, send):
print("Hello from the Middleware")
await self.app(scope, receive, send)
我以 Starlette TimingMiddleware 为灵感,但我无法将其与 aiohttp
整合。可能是因为它们的实现方式略有不同。
考虑到 ASGI 规范中有一段中间件,并且 aiohttp
和 Starlette
都实现了该规范,难道不应该有一种方法可以编写在两个?
如果是,我错过了什么?
- Flask 是一个 WSGI 框架。
- Starlette 是一个 ASGI 框架。
- aiohttp 既不支持 WSGI 也不支持 ASGI。 https://github.com/aio-libs/aiohttp/issues/2902
不可能让相同的中间件支持所有三个框架。
我们目前正在维护用多个 HTTP 框架(Flask、aiohttp 和 FastAPI)编写的代码。重写它们使它们都使用相同的框架目前是不可行的。我想在这些应用程序之间共享一些代码,它们非常适合中间件(日志配置、监控、身份验证……)。
最初的实现是通过子类化 Flask 完成的,并且在所有基于 Flask 的应用程序中都运行良好。但是在aiohttp或者FastAPI中是不可用的。
创建一个与框架无关的实现是可行的(理论上),今天早上我采用了一个更简单的案例并成功地将它转换为 WSGI 中间件并且能够将它集成到 Flask 应用程序中。
但是 ASGI 给我带来了一些麻烦,因为 纯 ASGI 中间件的文档不多。所有示例都显示了如何为 他们的 框架编写中间件。
official ASGI docs 在那个话题上也真的很“瘦”。据我所知,它应该看起来像这样(附带问题:“传递给构造函数的第二个参数是什么?”):
class MyMiddleware:
def __init__(self, app, something) -> None:
self.app = app
self.something = something # <- what is this second argument?
async def __call__(self, scope, receive, send):
print("Hello from the Middleware")
await self.app(scope, receive, send)
我以 Starlette TimingMiddleware 为灵感,但我无法将其与 aiohttp
整合。可能是因为它们的实现方式略有不同。
考虑到 ASGI 规范中有一段中间件,并且 aiohttp
和 Starlette
都实现了该规范,难道不应该有一种方法可以编写在两个?
如果是,我错过了什么?
- Flask 是一个 WSGI 框架。
- Starlette 是一个 ASGI 框架。
- aiohttp 既不支持 WSGI 也不支持 ASGI。 https://github.com/aio-libs/aiohttp/issues/2902
不可能让相同的中间件支持所有三个框架。