Skip to course content
Free FastAPI backend course

FastAPI for AI Backend Development

Unit 07.00: Dependencies as shared logic, declared

A dependency is shared logic declared in the signature rather than called at the top of every handler.

One rule, two endpoints, enforced before either

A dependency requiring a request id, used by two endpoints.

The code calls both, with and without the header.

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

app = FastAPI()


def require_request_id(x_request_id: str | None = Header(default=None)) -> str:
    if not x_request_id:
        raise HTTPException(status_code=400,
                            detail={"error": "missing_request_id"})
    return x_request_id


@app.get("/a")
def a(request_id: str = Depends(require_request_id)) -> dict:
    return {"endpoint": "a", "request_id": request_id}


@app.get("/b")
def b(request_id: str = Depends(require_request_id)) -> dict:
    return {"endpoint": "b", "request_id": request_id}


client = TestClient(app)
print(client.get("/a", headers={"X-Request-ID": "r-1"}).json())
print(f"missing header -> {client.get('/b').status_code}")

print("\nOne rule, declared in two signatures, enforced before either handler.")

The rule runs before either handler and neither endpoint contains the check. Adding a third endpoint means adding the parameter, not remembering the logic.

It also appears in the generated documentation, so a caller sees the header requirement rather than discovering it through a 400.

The mistake this prevents

The mistake is a helper function called as the first line of each handler. It works, and it is one an author can forget on the endpoint they add under time pressure - which will be the one that matters.

Takeaway

Declare shared request-time rules as dependencies. They run before the handler, appear in the docs, and cannot be forgotten by a new endpoint.