es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

“Transmita el valor de las dependencias de ‘include_router’ a las rutas de FastAPI.”

Me preguntaba si era posible pasar los resultados del argumento kwarg dependencies en include_router al router que se le pasa. Lo que quiero hacer es decodificar un JWT del encabezado x-token de una solicitud y pasar la carga útil decodificada a las rutas books.

Sé que podría simplemente escribir authenticate_and_decode_JWT como una dependencia de cada una de las rutas en routers/book.py, pero esto sería bastante repetitivo para una aplicación grande.

main.py

from typing import Optional
from jose import jwt

from fastapi import FastAPI, Depends, Header, HTTPException, status
from jose.exceptions import JWTError

from routers import books

app = FastAPI()

def authenticate_and_decode_JWT(x_token: str = Header(None)):
    try:
        payload = jwt.decode(x_token.split(' ')[1], 'secret key', algorithms=['HS256'])
        return payload
    except JWTError:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)

app.include_router(
    books.router,
    prefix="/books",
    dependencies=[Depends(authenticate_and_decode_JWT)], 
)

@app.get("/")
def read_root():
    return {"Hello": "World"}

routers/books.py

from fastapi import APIRouter

router = APIRouter()

@router.get('/')
def get_book():
    # realizar operaciones con los datos de usuario autenticado decodificados del payload de JWT aquí
    pass

@router.post('/')
def create_book():
    # realizar operaciones con los datos de usuario autenticado decodificados del payload de JWT aquí
    pass
Tags:  ,

Answer

  1. Avatar for davy.ai

    Sí, es posible pasar los resultados del argumento dependencies en include_router al enrutador que se le pasa. En este caso, se desea decodificar un JWT desde el encabezado x-token de una solicitud y pasar la carga útil decodificada a las rutas books.

    Para lograr esto, se puede pasar el payload devuelto por authenticate_and_decode_JWT como un parámetro a las funciones en books.py. Se puede modificar books.py para aceptar un parámetro payload en cada una de sus funciones y luego usarlo en consecuencia.

    Por ejemplo:

    @router.get('/')
    def get_book(payload: dict = Depends(authenticate_and_decode_JWT)):
        # hacer algo con los datos autenticados del usuario decodificados del payload de JWT aquí
        pass
    
    @router.post('/')
    def create_book(payload: dict = Depends(authenticate_and_decode_JWT)):
        # hacer algo con los datos autenticados del usuario decodificados del payload de JWT aquí
        pass
    

    De esta manera, no es necesario repetir la dependencia authenticate_and_decode_JWT en cada función, lo que hace que el código sea más conciso y fácil de mantener.

    Además, también se puede crear una subclase personalizada de Request que incluya el atributo payload y usarla en lugar de la clase de solicitud FastAPI. Esto permitiría acceder al atributo payload desde cualquier función en la aplicación, sin tener que pasarlo explícitamente como un parámetro.

    Por ejemplo:

    from fastapi import Request
    
    class AuthenticatedRequest(Request):
        def __init__(self, *args, payload: dict, **kwargs):
            super().__init__(*args, **kwargs)
            self.payload = payload
    
    @app.middleware("http")
    async def add_payload_to_request(request: Request, call_next):
        payload = await authenticate_and_decode_JWT(request.headers.get("x-token"))
        request = AuthenticatedRequest(request.scope, request.receive, payload=payload)
        response = await call_next(request)
        return response
    

    Aquí, se define una subclase personalizada AuthenticatedRequest que incluye un atributo payload. También se define una función middleware que utiliza authenticate_and_decode_JWT para extraer el payload del encabezado x-token, y luego crea un nuevo objeto AuthenticatedRequest con el payload incluido. Luego se pasa este nuevo objeto de solicitud a la siguiente función middleware (o a la función de ruta, si no hay más funciones middleware).

    Con este enfoque, se puede acceder al atributo payload desde cualquier función que acepte un parámetro Request:

    @router.get('/')
    def get_book(request: AuthenticatedRequest):
        # hacer algo con los datos autenticados del usuario decodificados del payload de JWT aquí 
        pass
    
    @router.post('/')
    def create_book(request: AuthenticatedRequest):
        # hacer algo con los datos autenticados del usuario decodificados del payload de JWT aquí
        pass
    

Comments are closed.