FastAPI - 无法从中间件访问路径参数

Iac*_*opo 4 python-3.x fastapi

我的典型路径是这样的

/user/{user_id}/resource/{resource_id}
Run Code Online (Sandbox Code Playgroud)

我有一个验证方法,已经用异步 python 编写,如下所示:

async def is_allowed(user_id: int, resource_id: int) -> bool
Run Code Online (Sandbox Code Playgroud)

返回一个布尔值:如果用户可以访问该资源,则返回 true,否则返回 false。

我想编写一个middleware调用is_allowed从路径中提取变量的程序。

我摆弄了一下,但找不到如何获取它们:我希望从request.path_params.

一个更完整的示例(根据@Marcelo Trylesinski 回答进行编辑):

import logging

from fastapi import FastAPI
from starlette.requests import Request
from starlette.responses import Response

app = FastAPI()

_logger = logging.getLogger()
_logger.setLevel(logging.DEBUG)


async def is_allowed(user_id, resource_id):
    _logger.error(user_id)
    _logger.error(resource_id)
    return True


@app.middleware('http')
async def acl(request: Request, call_next):
    user_id = request.path_params.get("user_id", None)
    resource_id = request.path_params.get("resource_id", None)
    allowed = await is_allowed(user_id, resource_id)
    if not allowed:
        return Response(status_code=403)
    else:
        return await call_next(request)


@app.get('/user/{user_id}/resource/{resource_id}')
async def my_handler(user_id: int, resource_id: int):
    return {"what": f"Doing stuff with {user_id} on {resource_id}"}
Run Code Online (Sandbox Code Playgroud)

记录的值为None.

Gab*_*lli 5

您将无法使用中间件来实现您的目标,因为中间件是在路由之前执行的。

因此 FastAPI/Starlette 不知道它将匹配哪个路径并且无法填充path_params.

您将不得不使用不同的解决方案,例如在 cookie、标头或查询参数上传递这些参数,或者使用装饰器/依赖项。

参考:

https://github.com/encode/starlette/issues/230

https://fastapi.tiangolo.com/tutorial/middleware/#middleware