Программирование с ИИ
ENRU
7.1

Как устроен бэкенд

запрос, обработчик, ответ

Что это

Бэкенд — программа, которая ждёт запросов и отвечает на них. Внутри она устроена всегда одинаково, на любом языке и фреймворке: запрос приходит, маршрутизатор решает, кто его обработает, обработчик делает работу, ответ уходит обратно.

Поняв эту цепочку один раз, ты ориентируешься в любом бэкенд-проекте — меняются слова и синтаксис, схема остаётся.

Как выглядит в коде

Схема из книги — будет перерисована для сайта
Путь запроса. Обработчик — единственное место, где находится твой код; всё остальное делает фреймворк.

Вот эта схема в коде. Рабочий пример на FastAPI:

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field

app = FastAPI()

SUBS: dict[int, list[str]] = {7: ["Oslo", "Bergen"]}


class SubOut(BaseModel):
    user_id: int
    cities: list[str]


@app.get("/subs/{user_id}", response_model=SubOut)
def get_subs(user_id: int) -> SubOut:
    if user_id not in SUBS:
        raise HTTPException(status_code=404, detail="пользователь не найден")
    return SubOut(user_id=user_id, cities=SUBS[user_id])

Запрос и ответ, по-настоящему:

curl -i http://127.0.0.1:8765/subs/7
измерено
HTTP/1.1 200 OK
server: uvicorn
content-length: 40
content-type: application/json

{"user_id":7,"cities":["Oslo","Bergen"]}
curl -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8765/subs/999
измерено
404

Как это читать

@app.get("/subs/{user_id}") — маршрут. Декоратор регистрирует функцию: «вызывай её на GET-запрос по такому адресу» (статья 2.9). Искать вызов get_subs в проекте бесполезно — её вызывает фреймворк.

user_id: int — часть адреса, превращённая в аргумент. Фреймворк вынет её из /subs/7 и преобразует в число. Если прислать /subs/abc, обработчик даже не запустится — придёт ошибка о неверном типе.

response_model=SubOut — форма ответа. Фреймворк проверит, что вернули именно её, и превратит в JSON.

raise HTTPException(404) — способ ответить ошибкой. Не return, а raise: исключение перехватывает фреймворк и превращает в HTTP-ответ (статья 2.8).

Что делает фреймворк, а что ты

Это главное для чтения чужого кода:

ФреймворкТы
принимает соединениерешаешь, что делать с данными
разбирает URL и находит обработчикходишь в базу
проверяет типы и схемырешаешь, что считать ошибкой
превращает результат в JSON
ловит исключения и отдаёт коды

Твоего кода в цепочке — одно звено. Поэтому в бэкенд-проекте файлов много, а читать надо в первую очередь обработчики.

Как сказать ИИ

Запрос
Покажи все маршруты этого проекта: метод, адрес и функция,
которая его обрабатывает. Таблицей, без кода.
Запрос
Что произойдёт при GET /subs/abc? Обработчик запустится
или ошибка будет раньше?
Запрос
Добавь обработчик GET /subs/{user_id}/count — возвращает
число подписок. 404, если пользователя нет. Остальные
маршруты не трогай.

На что смотреть

Логика внутри обработчика. Обработчик должен принять запрос, вызвать нужное и вернуть результат. Если в нём пятьдесят строк с SQL и бизнес-правилами — дальше этот код не переиспользовать и не протестировать.

Обращение к базе прямо в обработчике. То же самое: запросы выносят в отдельный модуль, чтобы их можно было менять, не трогая маршруты.

Ответ без схемы. Без response_model фреймворк отдаст что угодно, включая поля, которых пользователь видеть не должен.

return вместо raise при ошибке. Вернуть {"error": "не найден"} с кодом 200 — значит соврать клиенту: формально всё хорошо.

Шпаргалка

  • Цепочка одинакова везде: клиент → маршрут → обработчик → база → ответ.

  • Твой код — только обработчик, остальное делает фреймворк.

  • Маршрут регистрируется декоратором; вызов функции в проекте не найдётся.

  • Ошибку возвращают через raise, а не return.

  • Незнакомый бэкенд читай со списка маршрутов — это его оглавление.

  • Логика и запросы к базе выносятся из обработчика.