#Is before_request the best way to "autouse" some Depends-like logic?

1 messages · Page 1 of 1 (latest)

serene mango
#

I'm trying to migrate a FastAPI pattern to Litestar.
The original one is something like:

from contextvars import ContextVar
from typing import Annotated, Any

from fastapi import Depends, FastAPI, Header, Request
from pydantic import Field

logging_context: ContextVar[dict[str, Any] | None] = ContextVar("logging_context", default=None)


async def update_context(
    request: Request,
    correlation_id: Annotated[str, Field(pattern=r"...")] = Header(),
) -> None:
    context = {"correlation_id": correlation_id}
    if token := request.state.get("jwt_token", None):
        context["user"] = token.user
    logging_context.set(context)


app = FastAPI(dependencies=[Depends(update_context)])

For the uncorrupted, this would allow the dependency to be called before every endpoint, which adds some information to a global contextvar that would later be used for logging. "Authors of Business Logic" don't have to do any configuration themselves to enjoy coherent logging.

Moving this into Litestar, I realized there isn't a way to use the dependency without calling it explicitly. I managed to get what I want with before_request, but is this the best way to do it?

async def before_request_app(request: Request) -> None:
    context = {}
    if (correlation_id := request.headers.get("correlation-id")) and re.match(r"...", correlation_id):
        context["correlation_id"] = correlation_id
    if token := request.state.get("token", None):
        context["user"] = token.user
    logging_context.set(context)


app = Litestar(
    route_handlers=[index],
    logging_config=logging_config(),
    before_request=before_request_app,
)

Or is there another way to achieve this, preferrably without using structlog?
My "reservations" with this is just that it isn't foolproof, if another author uses a before_request in an inner layer, it will get overridden.
Thanks in advance for your time

upbeat valley
#

I'd use a middleware

#

before_request also only applies to routes that have a Request, so it won't trigger on ASGI and WebSocket routes

#

A middleware can apply to all routes

serene mango
#

just gotta make sure this middleware is after the jwt validation 😅