Урок по треку Сети и HTTP 8 мин

Проектирование API за 8 минут

REST-ресурсы, коды ответов, пагинация, версионирование, идемпотентность, сравнение с GraphQL и gRPC.

REST это стиль, а не протокол: API строится вокруг ресурсов (сущностей), к которым применяются стандартные методы HTTP. Хорошее API предсказуемо: зная пару эндпоинтов, угадываешь остальные.

Ресурсы и URL

GET    /orders              список
POST   /orders              создать
GET    /orders/981          один заказ
PATCH  /orders/981          частично изменить
DELETE /orders/981          удалить
GET    /orders/981/items    вложенный ресурс
  • Существительные во множественном числе, без глаголов: не /getOrders, не /orders/create.
  • Действия, которые не ложатся в CRUD, оформляют как подресурс: POST /orders/981/cancel или как смену поля PATCH /orders/981 {"status":"cancelled"}.
  • Фильтры, сортировка и поиск в query: /orders?status=paid&sort=-createdAt.

Коды ответов

201 Created + Location при создании, 204 при удалении, 404 нет ресурса, 409 конфликт (email занят), 422 или 400 при невалидных данных, 401 и 403, 429 при превышении лимита. Ошибки в одном формате, например Problem Details (RFC 9457):

{ "type": "https://api.example/errors/validation", "title": "Validation failed",
  "status": 422, "errors": [{ "field": "email", "message": "required" }] }

Пагинация

Offset: ?limit=20&offset=40. Просто, можно прыгнуть на страницу 7. Минусы: OFFSET 100000 медленный (базе надо пропустить строки), а если между запросами добавились записи, элементы на границе страниц дублируются или теряются.

Cursor (keyset): ?limit=20&after=eyJpZCI6OTgxfQ. Курсор кодирует позицию (например, createdAt и id последнего элемента), запрос WHERE (created_at, id) < (...) ORDER BY ... LIMIT 20 работает по индексу одинаково быстро на любой глубине и стабилен при вставках. Минус: нельзя прыгнуть на произвольную страницу. Подходит для лент и бесконечной прокрутки.

Версионирование

  • В пути: /v1/orders. Просто и наглядно, самый частый вариант.
  • В заголовке: Accept: application/vnd.example.v2+json или свой заголовок.
  • Главное правило: не ломать клиентов. Добавить необязательное поле можно без новой версии. Удалить или переименовать поле, сменить тип или смысл это breaking change.

Идемпотентность и надёжность

Сеть рвётся, клиент повторяет запрос. GET, PUT, DELETE повторять безопасно. Для POST, создающего платёж или заказ, клиент шлёт Idempotency-Key, сервер хранит результат по ключу и на повтор отдаёт его же. Для конкурентных изменений: ETag + If-Match (оптимистическая блокировка). Для защиты от перегрузки: rate limit с 429 и Retry-After.

REST, GraphQL, gRPC

  • REST: просто, кешируется HTTP-средствами, понятен всем. Минусы: over-fetching (пришло лишнее) и under-fetching (нужно 5 запросов для одного экрана).
  • GraphQL: один эндпоинт, клиент сам описывает, какие поля нужны. Удобно для сложных экранов и многих клиентов. Минусы: HTTP-кеш почти не работает (обычно POST на один URL), нужна защита от тяжёлых запросов (глубина, сложность), проблема N+1 на сервере (решается DataLoader).
  • gRPC: бинарный Protobuf поверх HTTP/2, строгий контракт, стриминг, кодогенерация. Хорош между сервисами. Из браузера напрямую не работает, нужен gRPC-Web и прокси.

Частые ошибки

  • Глаголы в URL и POST на всё.
  • Пагинация без лимита сверху: клиент просит limit=1000000.
  • Разный формат ошибок в разных эндпоинтах.
  • Breaking change без новой версии.

Что спросят на собесе

  • Какие принципы REST ты знаешь, как назвать эндпоинты для заказа и его отмены?
  • Offset или cursor пагинация: плюсы и минусы.
  • Как версионировать API и что считается breaking change?
  • Как сделать безопасный повтор создания платежа?
  • Когда выбрать GraphQL или gRPC вместо REST?

Закрепите за 5 минут

После урока в тренажёре 3-5 проверочных вопросов, дальше модуль уходит в повторения.