Тема 4 из 6

Зависимости и доступ

Часто одни и те же действия нужны многим маршрутам: прочитать параметры страницы, проверить ключ, найти пользователя. В FastAPI для этого есть зависимости.

Depends

from fastapi import Depends, Query


def pagination(skip: int = Query(0, ge=0), limit: int = Query(10, ge=1, le=50)):
    return {"skip": skip, "limit": limit}


@app.get("/todos")
def todos(page: dict = Depends(pagination)):
    return TODOS[page["skip"]:page["skip"] + page["limit"]]

Перед вызовом маршрута FastAPI вызовет pagination, заполнив её параметры из запроса, и передаст результат в page. Если параметры неверные — ответ 422, как обычно. Зависимость пишется один раз и подключается к любому числу маршрутов; в /docs её параметры видны у каждого из них.

Заголовки

from fastapi import Header


def require_key(x_api_key: str | None = Header(None)):
    ...

Header() читает заголовок запроса. Подчёркивания в имени параметра превращаются в дефисы: x_api_key ↔ X-Api-Key. Header() без значения по умолчанию делает заголовок обязательным (без него — 422); Header(None) — необязательным, и проверку вы делаете сами.

Кто вы и можно ли вам

def current_user(x_api_key: str | None = Header(None)):
    if x_api_key not in USERS:
        raise HTTPException(401, "Нужен ключ доступа")
    return USERS[x_api_key]


def require_admin(user: dict = Depends(current_user)):
    if user["role"] != "admin":
        raise HTTPException(403, "Только для админов")
    return user


@app.delete("/todos/{tid}")
def delete(tid: int, admin: dict = Depends(require_admin)):
    ...
  • 401 Unauthorized — «не знаю, кто вы»: нет ключа или он неверный;
  • 403 Forbidden — «знаю, кто вы, но вам нельзя»;
  • зависимости строятся друг на друге: require_admin использует current_user. FastAPI вызовет их по цепочке, и каждая может прервать запрос своим HTTPException.

В настоящих проектах вместо простых ключей обычно используют токены (OAuth2, JWT): в FastAPI для этого есть OAuth2PasswordBearer из fastapi.security, и устроено всё так же — через зависимость.

Итог

  • Depends(функция) — вызвать функцию перед маршрутом и передать результат;
  • параметры зависимости (Query, Header) заполняются из запроса;
  • Header(None) — необязательный заголовок, x_api_key ↔ X-Api-Key;
  • 401 — кто вы, 403 — нельзя; зависимости строятся цепочкой.