FastAPI - 无法从中间件访问路径参数
FastAPI - can't access path parameters from middleware
我的典型路径是这样的
/user/{user_id}/resource/{resource_id}
我有一个验证方法,已经用异步 python 编写,如下所示:
async def is_allowed(user_id: int, resource_id: int) -> bool
那 returns 一个布尔值:如果用户可以访问资源则为 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}"}
记录的值为 None
。
使用中间件将无法实现您的目标,因为中间件在路由之前执行。
因此FastAPI/Starlette不知道它将匹配到哪条路径并且无法填充path_params
。
您将不得不使用不同的解决方案,例如将这些参数传递给 cookie、header 或查询 arg,或者使用 decorator/Dependency.
参考:
https://github.com/encode/starlette/issues/230
https://fastapi.tiangolo.com/tutorial/middleware/#middleware
我的典型路径是这样的
/user/{user_id}/resource/{resource_id}
我有一个验证方法,已经用异步 python 编写,如下所示:
async def is_allowed(user_id: int, resource_id: int) -> bool
那 returns 一个布尔值:如果用户可以访问资源则为 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}"}
记录的值为 None
。
使用中间件将无法实现您的目标,因为中间件在路由之前执行。
因此FastAPI/Starlette不知道它将匹配到哪条路径并且无法填充path_params
。
您将不得不使用不同的解决方案,例如将这些参数传递给 cookie、header 或查询 arg,或者使用 decorator/Dependency.
参考:
https://github.com/encode/starlette/issues/230
https://fastapi.tiangolo.com/tutorial/middleware/#middleware