Mi camino típico es algo así como
/user/{user_id}/resource/{resource_id}Tengo un método de validación, ya escrito en python asíncrono, como este:
async def is_allowed(user_id: int, resource_id: int) -> boolEso devuelve un booleano: verdadero si el usuario puede acceder al recurso, falso de lo contrario.
Quiero escribir un middleware que llame is_allowed extrayendo las variables de la ruta.
Jugueteé, pero no puedo encontrar cómo obtenerlos: esperaba obtener esta información de request.path_params .
Un ejemplo de alguna manera más completo (editado siguiendo la respuesta de @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}"} Los valores registrados son None .
No podrá lograr su objetivo con un Middleware, porque los Middlewares se ejecutan antes del enrutamiento.
Por lo tanto, FastAPI/Starlette no sabe con qué ruta coincidirá y no puede path_params .
Tendrá que usar una solución diferente, como pasar estos parámetros en una cookie, encabezado o argumento de consulta, o usar un decorador/Dependencia.
Referencia:
https://github.com/encode/starlette/issues/230
https://fastapi.tiangolo.com/tutorial/middleware/#middleware