fastapi依赖与中间件

Pra*_*hat 16 python fastapi

我是 fastapi 新手。我使用过其他语言的多个 Web 框架,并发现了用于各种目的的中间件的通用模式。例如,如果我有一个想要进行身份验证的 API 路由,那么我会使用一个中间件来进行身份验证。如果我想增加传入请求,我会使用中间件。FastAPI 确实有中间件(文档中很小的一部分),但也有依赖项。我希望验证我的 API 路由,并开始寻找示例,我发现的所有示例都使用依赖项。建议采用什么方式(依赖项或中间件)来验证 API 路由?为什么?

lsa*_*abi 20

我的看法是:

  • Dependency:您可以使用它来运行用于准备变量、身份验证等的代码。
  • Middleware:您需要先检查一些内容,然后拒绝或将请求转发给您的逻辑。

中间件可以看作是 Dependency 的超集,因为后者是一种返回可在请求中使用的值的中间件。不过,在中间件中,您可以记录请求或缓存结果并访问请求的响应(甚至转发请求、调用其他 API 等)。

长话短说

依赖关系是处理请求之前所需的一种常见逻辑(例如,我需要与此令牌关联的用户 ID),而中间件可以做到这一点,它还可以访问对该请求的响应。依赖关系是创建身份验证中间件的首选方式


piy*_*ere 9

一般来说,@lsabi给出的答案是正确的。

但在 FastAPI 的上下文中,无法在特定 API 路由器上定义中间件(截至 2022 年 8 月)。
所有中间件通常都在全局应用程序级别(尽管您可以编写自己的逻辑,通过正则表达式/过滤仅将其应用到特定路由,在我看来,这不是很干净的解决方案),如果这是您想要的唯一方法,那么您有为每个路线创建一个单独的应用程序(使用安装),然后您可以编写自己的中间件,如下所述: https ://github.com/tiangolo/fastapi/issues/1174#issuecomment-605508353

但对于路由依赖,这个说法并不完全正确:

中间件可以看作是 Dependency 的超集

尽管根据定义,依赖项不会拒绝/转发内容,但在 FastAPI 中,您始终可以从依赖项引发异常(可能是 HTTPException),这将导致它在请求到达路由处理程序之前拒绝请求。

所以你可以做类似的事情:

async def auth_middleware(request: Request):
   # your code to check if user is authenticated
   # ...
   raise HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Not authenticated bruh"
    )

router = APIRouter(dependencies=[Depends(auth_middleware)])
Run Code Online (Sandbox Code Playgroud)

现在,在执行router上定义的任何路由处理程序之前,首先它将运行auth_middleware函数。这正是中间件应该如何工作的。

这里唯一需要注意的是,因为它是一个依赖项,所以它必须在路由处理程序之前运行。
因此,如果您的用例要求您稍后处理某些事情,那么这是行不通的。我没有遇到任何这样的要求,选择性 gzip 压缩可能是一个例子,但无论如何你不应该在 python 中 gzip 压缩你的 http 响应。

希望有帮助!