Выбрать код ответа для каждого исхода метода — успех, ошибка запроса, нет прав, конфликт состояния, перегрузка, сбой — и описать тело ошибки так, чтобы клиент мог на него отреагировать.
Код ответа — часть контракта
Код ответа — часть контракта
Классы кодов:
• 2xx — успех;
• 3xx — перенаправление;
• 4xx — ошибка клиента: повтор без исправления не поможет; исключение — 429, его повторяют после паузы из Retry-After;
• 5xx — ошибка сервера: повтор позже может помочь.
Для выпускников курса по тестированию это повторение. Аналитику важнее, какой код записать в контракт на каждый исход метода.
401 или 403? Спросите: поможет ли войти заново? Если да — 401: клиент не опознан, токена нет или он истёк. Если нет — 403: клиента знаем, но прав не хватает. Когда само существование ресурса — секрет, вместо 403 отвечают 404: так сервис заказов отвечает на запрос чужого заказа.
400, 409 и 422:
• 400 — запрос не удалось разобрать: битый JSON, «два» вместо числа;
• 422 — запрос разобран, но данные нарушают правило: пустая корзина, адрес вне зоны;
• 409 — мешает текущее состояние ресурса: отмена доставленного заказа.
Границу 400/422 API проводят по-разному, поэтому её фиксируют в контракте.
Антипаттерн — «200 с ошибкой внутри»: код 200 и тело {"success": false}. Повторы, мониторинг и кэши смотрят на код и видят успех.
Тело ошибки — в едином формате, например Problem Details (RFC 9457, тип application/problem+json): поля type, title, status, detail и свои расширения. Ответ 409 на отмену заказа в статусе in_delivery (в доставке):
{"type": "https://api.romashka.example/problems/order-not-cancellable", "title": "Заказ нельзя отменить", "status": 409, "currentStatus": "in_delivery"}
Коды, которые чаще всего пишут в контракт
| Код | Когда | Пример «Ромашки» |
|---|---|---|
| 200 OK | успех с телом | GET заказа |
| 201 Created | создан ресурс, его адрес — в Location | POST /orders |
| 202 Accepted | принято, выполним позже | запуск возврата денег |
| 204 No Content | успех без тела | удалён сохранённый адрес |
| 400 Bad Request | запрос не разобрать | "quantity": "два" |
| 401 Unauthorized | токена нет или он неверный | токен истёк |
| 403 Forbidden | личность известна, прав нет | возврат без роли «финансы» |
| 404 Not Found | ресурса нет (или он скрыт) | несуществующий или чужой заказ |
| 409 Conflict | мешает текущее состояние | отмена доставленного заказа |
| 422 Unprocessable Content | данные нарушают правило | пустая корзина |
| 429 Too Many Requests | превышен лимит, пауза — в Retry-After | 300 запросов в секунду при лимите 100 |
| 500 Internal Server Error | сбой у нас | ошибка в коде сервиса заказов |
| 502 Bad Gateway | вызванная система вернула негодный ответ | провайдер прислал битый ответ |
| 503 Service Unavailable | перегрузка или обслуживание | сервис заказов на обслуживании |
| 504 Gateway Timeout | вызванная система не ответила вовремя | провайдер молчит |
Конспект урока
Код ответа — часть контракта
Классы кодов:
• 2xx — успех;
• 3xx — перенаправление;
• 4xx — ошибка клиента: повтор без исправления не поможет; исключение — 429, его повторяют после паузы из Retry-After;
• 5xx — ошибка сервера: повтор позже может помочь.
Для выпускников курса по тестированию это повторение. Аналитику важнее, какой код записать в контракт на каждый исход метода.
401 или 403? Спросите: поможет ли войти заново? Если да — 401: клиент не опознан, токена нет или он истёк. Если нет — 403: клиента знаем, но прав не хватает. Когда само существование ресурса — секрет, вместо 403 отвечают 404: так сервис заказов отвечает на запрос чужого заказа.
400, 409 и 422:
• 400 — запрос не удалось разобрать: битый JSON, «два» вместо числа;
• 422 — запрос разобран, но данные нарушают правило: пустая корзина, адрес вне зоны;
• 409 — мешает текущее состояние ресурса: отмена доставленного заказа.
Границу 400/422 API проводят по-разному, поэтому её фиксируют в контракте.
Антипаттерн — «200 с ошибкой внутри»: код 200 и тело {"success": false}. Повторы, мониторинг и кэши смотрят на код и видят успех.
Тело ошибки — в едином формате, например Problem Details (RFC 9457, тип application/problem+json): поля type, title, status, detail и свои расширения. Ответ 409 на отмену заказа в статусе in_delivery (в доставке):
{"type": "https://api.romashka.example/problems/order-not-cancellable", "title": "Заказ нельзя отменить", "status": 409, "currentStatus": "in_delivery"}