Ресурсы, URL, методы и статусы: правила хорошего REST
↑ 5.1 Проектирование REST API · → Следующая
Зачем это на собесе
«Спроектируйте REST API для заказов» — почти обязательное задание. Смотрят на именование ресурсов, методы, коды и последовательность.
Объяснение
REST — стиль, где всё — ресурс с URL, а действия выражаются HTTP-методами.
| Метод | Смысл | Идемпотентен | Безопасен |
|---|---|---|---|
| GET | получить | да | да |
| POST | создать / выполнить действие | нет | нет |
| PUT | заменить целиком | да | нет |
| PATCH | частично изменить | обычно нет | нет |
| DELETE | удалить | да | нет |
GET /orders список (с пагинацией и фильтрами)
POST /orders создать → 201 + Location
GET /orders/{id} получить
PUT /orders/{id} заменить
PATCH /orders/{id} изменить часть
DELETE /orders/{id} удалить → 204
GET /orders/{id}/items вложенная коллекция
POST /orders/{id}/cancel действие (не CRUD) — допустимо как под-ресурсПравила:
- Существительные во множественном числе, без глаголов в URL (
/orders, а не/getOrders). - Вложенность не глубже 2 уровней; иначе выносите ресурс на верхний уровень с фильтром.
- Единый формат ошибок (ProblemDetails) и статусов (см. Ответы и ошибки: IResult, ProblemDetails, статус-коды).
- Даты — ISO 8601 UTC, идентификаторы — стабильные (GUID/ULID), поля — camelCase.
- HATEOAS в реальных API применяют редко.
Нюансы и подводные камни
- «Действия» вроде оплаты и отмены — не CRUD: используйте под-ресурс (
POST /orders/{id}/payments) или команду. - PUT требует полного представления; PATCH — JSON Merge Patch или JSON Patch.
- 200 с ошибкой в теле — антипаттерн.
- Не возвращайте разные формы для одного ресурса в зависимости от контекста без причины.
- Уровень зрелости Ричардсона: 2 (ресурсы + методы + коды) — обычная практика.
Практика
- Спроектируйте API интернет-магазина: заказы, позиции, платежи, возвраты.
- Опишите его в OpenAPI и проверьте линтером (Spectral).
- Проведите ревью существующего API на соответствие правилам.
Вопросы с ответами
PUT или PATCH?
PUT заменяет ресурс целиком и идемпотентен; PATCH меняет часть и передаёт только изменяемые поля.
Как выразить действие, не укладывающееся в CRUD?
Под-ресурсом-командой (
POST /orders/{id}/cancel) или созданием ресурса-события (POST /orders/{id}/cancellations).
Что такое идемпотентность метода?
Повторный вызов даёт то же состояние системы, что и один.