Прежде чем писать бэкенд, нужно понять как вообще работает веб. Когда вы вводите адрес в браузере и нажимаете Enter — происходит не магия, а чёткая последовательность действий которую можно объяснить и воспроизвести в коде.
Браузер отправляет запрос на сервер. Сервер обрабатывает запрос и отправляет ответ. Браузер отображает результат.
Протокол по которому происходит этот обмен называется HTTP (HyperText Transfer Protocol). Это текстовый протокол — запросы и ответы это обычный структурированный текст. Всё что делает браузер, мобильное приложение или ваш Python-скрипт обращаясь к серверу — отправляет HTTP-запросы и читает HTTP-ответы.
HTTP-запрос состоит из трёх частей: стартовая строка, заголовки и тело.
GET /products?category=1 HTTP/1.1
Host: shop.example.com
Accept: application/json
Authorization: Bearer abc123
(тело пустое — GET-запросы обычно не имеют тела)
Стартовая строка содержит три элемента:
- Метод — что мы хотим сделать (
GET,POST,PUT,DELETE) - Путь — к какому ресурсу обращаемся (
/products) - Версия протокола —
HTTP/1.1
Заголовки — метаданные запроса: кто отправляет, какой формат принимает, токен авторизации и так далее.
Тело — данные которые отправляются серверу. Есть только у POST и PUT запросов — когда нужно передать новые данные.
Ответ сервера имеет схожую структуру:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 234
{
"id": 1,
"name": "Ноутбук Lenovo",
"price": 75000.00
}
Статусная строка содержит версию протокола и код статуса — трёхзначное число которое сразу говорит что произошло.
Заголовки — метаданные ответа: тип содержимого, размер, кэширование.
Тело — сами данные. В современных API это почти всегда JSON.
Код статуса — главный способ которым сервер сообщает результат операции. Коды разбиты на группы по первой цифре:
| Код | Название | Когда используется |
|---|---|---|
200 OK |
Всё хорошо | Успешный GET, успешный PUT/DELETE |
201 Created |
Создано | Успешный POST — создан новый ресурс |
204 No Content |
Нет содержимого | Успешное удаление — возвращать нечего |
Клиент сделал что-то не то: неверный запрос, нет прав, ресурс не найден.
| Код | Название | Когда используется |
|---|---|---|
400 Bad Request |
Неверный запрос | Невалидные данные, неверный формат |
401 Unauthorized |
Не авторизован | Нужен токен авторизации |
403 Forbidden |
Запрещено | Авторизован, но нет прав |
404 Not Found |
Не найдено | Ресурс не существует |
422 Unprocessable Entity |
Ошибка валидации | Данные пришли, но не прошли проверку |
Клиент всё сделал правильно, но сервер не смог обработать запрос.
| Код | Название | Когда используется |
|---|---|---|
500 Internal Server Error |
Внутренняя ошибка | Что-то сломалось на сервере |
503 Service Unavailable |
Сервис недоступен | Сервер перегружен или на обслуживании |
Коды статусов — это соглашение, не обязательство. Технически можно вернуть
200при ошибке. Но хороший API использует коды правильно — клиент сразу понимает что произошло без разбора тела ответа.
Метод говорит серверу что клиент хочет сделать с ресурсом. Четыре основных метода:
Запрашивает данные. Не изменяет состояние сервера. Может вызываться сколько угодно раз — результат одинаков:
GET /users — получить список всех пользователей
GET /users/5 — получить пользователя с id=5
GET /products?category=1 — получить товары категории 1
Отправляет данные для создания новой записи. Каждый вызов создаёт новый ресурс:
POST /users
Body: {"name": "Алексей", "email": "alex@mail.ru"}
→ Создаёт нового пользователя
→ Возвращает 201 Created + данные созданного пользователя
Полностью заменяет данные ресурса. Адресуется к конкретному объекту по id:
PUT /users/5
Body: {"name": "Алексей Смирнов", "email": "alex@mail.ru", "city": "Москва"}
→ Полностью обновляет пользователя с id=5
→ Возвращает 200 OK + обновлённые данные
Удаляет указанный ресурс:
DELETE /users/5
→ Удаляет пользователя с id=5
→ Возвращает 204 No Content (тело пустое — удалять нечего)
Вы уже работали с CRUD в SQL. HTTP-методы — это CRUD на уровне веба:
| CRUD | SQL | HTTP-метод |
|---|---|---|
| Create | INSERT |
POST |
| Read | SELECT |
GET |
| Update | UPDATE |
PUT |
| Delete | DELETE |
DELETE |
REST (Representational State Transfer) — это не протокол и не стандарт. Это архитектурный стиль — набор соглашений о том как проектировать API поверх HTTP.
Когда говорят "REST API" или "RESTful API" — имеют в виду что API следует этим соглашениям. Если оно не следует — это просто "HTTP API".
В REST API URL описывает ресурс (существительное), а HTTP-метод описывает действие (глагол):
# Правильно: URL — существительное, действие — в методе
GET /users — получить всех пользователей
POST /users — создать пользователя
GET /users/5 — получить пользователя 5
PUT /users/5 — обновить пользователя 5
DELETE /users/5 — удалить пользователя 5
# Неправильно: глагол в URL — не REST
GET /getUsers
POST /createUser
GET /deleteUser?id=5
REST — набор архитектурных принципов и рекомендаций, а не технический стандарт. Нет программы которая проверит соответствует ли API стандарту REST. Разработчики следуют соглашениям добровольно: URL описывает ресурс, метод описывает действие, используются стандартные коды статусов. Это делает API предсказуемым и понятным.
Связанные ресурсы выражаются через вложенные пути:
GET /users/5/orders — все заказы пользователя 5
GET /users/5/orders/12 — конкретный заказ 12 пользователя 5
POST /users/5/orders — создать заказ для пользователя 5
Клиент-сервер — разделение ответственности. Фронтенд (браузер, мобильное приложение) и бэкенд (сервер) — это независимые части которые общаются через API. Фронтенд не знает как устроена база данных, бэкенд не знает как выглядит интерфейс.
Без состояния (stateless) — каждый запрос содержит всю информацию необходимую для его обработки. Сервер не помнит предыдущие запросы. Если нужна авторизация — токен передаётся в каждом запросе, а не хранится на сервере между обращениями.
Единообразный интерфейс — стандартные URL, стандартные методы, стандартные коды статусов. Разработчик знакомый с REST сразу понимает как работать с любым RESTful API.
JSON (JavaScript Object Notation) — текстовый формат для структурированных данных. Стал стандартом для REST API потому что:
- Читается человеком
- Парсится любым языком программирования
- Напрямую отображается на Python-словари и списки
{
"id": 1,
"name": "Алексей Смирнов",
"email": "alexey@gmail.com",
"city": "Москва",
"orders": [
{
"id": 10,
"status": "delivered",
"total": 80500.00
}
]
}Python умеет работать с JSON через встроенный модуль json:
import json
# Python → JSON (сериализация)
data = {'name': 'Алексей', 'city': 'Москва'}
json_string = json.dumps(data, ensure_ascii=False)
print(json_string)
# {"name": "Алексей", "city": "Москва"}
# JSON → Python (десериализация)
json_string = '{"id": 1, "name": "Алексей"}'
data = json.loads(json_string)
print(data['name']) # АлексейВ FastAPI который мы изучим в следующих уроках — JSON-сериализация происходит автоматически. Вы возвращаете Python-словарь, FastAPI превращает его в JSON-ответ.
К этому моменту вы умеете работать с базой данных через репозитории. Теперь посмотрим как это встраивается в бэкенд:
Клиент (браузер / мобильное приложение)
│
│ HTTP-запрос: GET /products/1
▼
┌──────────────────────────────────────┐
│ Бэкенд-приложение │
│ │
│ Роутер — разбирает URL и │
│ направляет к нужной │
│ функции-обработчику │
│ │
│ Схема/ — проверяет данные │
│ Валидация запроса │
│ │
│ Обработчик — бизнес-логика │
│ (view) │
│ │
│ Репозиторий — работа с базой │ ← это вы уже умеете
│ данных │
│ │
│ Схема — формирует ответ │
│ ответа (сериализация) │
└──────────────────────────────────────┘
│
│ HTTP-ответ: 200 OK + JSON
▼
Клиент получает данные и отображает их
Репозитории которые вы написали в Модуле 2 — это нижний слой этой схемы. В следующих уроках вы добавите остальные слои: роутеры, схемы, обработчики. Цепочка замкнётся.
- Из каких трёх частей состоит HTTP-запрос?
- Чем
400отличается от500? - Какой HTTP-метод использовать чтобы получить список всех товаров? А чтобы создать новый товар?
- Что означает "REST — это не протокол, а соглашение"?
- Почему URL
/getUsersнарушает принципы REST, а/users— нет? - Что означает принцип "без состояния" (stateless) в REST?
- Какой код статуса вернуть если пользователь запросил товар с
id=999, которого нет в базе? - Чем
PUT /users/5отличается отPOST /users? - Зачем нужен JSON если Python умеет работать со словарями напрямую?
- Посмотрите на схему из урока. Какую часть этой схемы вы уже умеете реализовывать после Модуля 2?
Это концептуальный урок — вместо задач с кодом проверьте понимание через следующие вопросы. Ответьте письменно своими словами.
Вы проектируете API для библиотеки из практической работы Модуля 1 (книги, авторы, читатели, выдачи). Опишите минимум 8 эндпоинтов: для каждого укажите метод, URL и что он делает.
Клиент отправил POST /users с телом {"name": ""} (пустое имя). Какой код статуса должен вернуть сервер и почему?
Объясните своими словами разницу между фронтендом и бэкендом используя принцип клиент-сервер из REST.