Lesson 5 / 26

Dependency Injection With Depends

Reusable request logic.

Auth, pagination, database sessions

Depends() declares that an endpoint needs the result of another function: the current user from a token, a database session, pagination parameters, settings. Dependencies can have their own dependencies and parameters (headers, queries), raise HTTPException to stop a request (401, 403), and use yield to clean up resources such as database sessions after the response. The Annotated[type, Depends(fn)] style keeps signatures clear and reusable.

Authentication and capped pagination as dependencies, run

I ran this with Python 3.12, FastAPI 0.142.2, Pydantic 2.13 and Starlette 1.7, calling the app through FastAPI's TestClient (no server needed). Without a header the dependency returns 401; with a wrong token, 403; with a valid token the user is resolved and the requested limit of 500 is capped to 50.

from typing import Annotated
from fastapi import Depends, FastAPI, Header, HTTPException
from fastapi.testclient import TestClient

TOKENS = {"secret-asha": "asha"}

def current_user(authorization: Annotated[str | None, Header()] = None) -> str:
    if not authorization or not authorization.startswith("Bearer "):
        raise HTTPException(status_code=401, detail="Missing bearer token")
    user = TOKENS.get(authorization.removeprefix("Bearer "))
    if user is None:
        raise HTTPException(status_code=403, detail="Invalid token")
    return user

def pagination(limit: int = 10, offset: int = 0) -> dict:
    return {"limit": min(limit, 50), "offset": offset}       # reusable, capped

app = FastAPI()

@app.get("/orders")
def orders(user: Annotated[str, Depends(current_user)],
           page: Annotated[dict, Depends(pagination)]):
    return {"user": user, **page}

client = TestClient(app)
print(client.get("/orders").status_code, client.get("/orders").json())
print(client.get("/orders", headers={"Authorization": "Bearer nope"}).json())
print(client.get("/orders?limit=500", headers={"Authorization": "Bearer secret-asha"}).json())

Output:

401 {'detail': 'Missing bearer token'}
{'detail': 'Invalid token'}
{'user': 'asha', 'limit': 50, 'offset': 0}

Use yield dependencies for sessions

A dependency that yields a database session and closes it afterwards guarantees cleanup even when the endpoint raises.

Quick check: How does a dependency reject an unauthenticated request?

  • By returning None silently
  • By raising HTTPException with status 401
  • By printing a warning
  • By crashing the server
Answer

By raising HTTPException with status 401 — Dependencies can short-circuit requests.