Опирается на правила:
R-PRIN-1..4,R-URL-1..3,R-RES-1..3,R-MTH-1..6,R-NEST-1..4из REST API Style Guide → раздел URL и ресурсы.
Важно знать
- 4 принципа: предсказуемость, единообразие, читаемость, стабильность.
- URL — часть публичного контракта, изменение = breaking change.
- HATEOAS-ссылки в теле запрещены, навигация — в OpenAPI.
- kebab-case, lowercase, без trailing slash, без
.json-расширений.- Коллекции — множественное число (
/orders); singleton — единственное (/profile).- HTTP-методы по семантике: GET без эффектов, POST для создания/команд.
- 2 уровня вложенности максимум. Глубже — flat resource с filter.
- Path-переменная в дизайне URL всегда
{id}(контекст задан именем ресурса).
REST URL — это первая документация API. Хорошо сделанный URL angular ясен без чтения OpenAPI: разработчик угадывает GET /orders/{id}/items по аналогии с GET /orders. UCP формулирует правила так, чтобы каждый эндпоинт читался как фраза на английском.
Принципы
R-PRIN-1..4:
- Предсказуемость — знающий один эндпоинт угадывает остальные.
- Единообразие — одни правила для всех контекстов.
- Читаемость — URL читается как фраза:
GET /orders/{id}/items= «get order's items». - Стабильность — URL — публичный контракт, изменение = breaking change.
R-PRIN-X1: HATEOAS-ссылки запрещены. Тело ответа не содержит _links: { ... }. Единственное исключение — заголовок Location при создании ресурса. Навигация описывается в OpenAPI.
Формат пути
R-URL-1..3:
/api/v1/order-items ✓
/api/v1/delivery-addresses ✓
/api/v1/users/{id}/profile ✓
/api/v1/OrderItems ✗ — заглавные
/api/v1/order_items ✗ — snake_case
/api/v1/deliveryAddresses ✗ — camelCase
/api/v1/orders/ ✗ — trailing slash
/api/v1/orders.json ✗ — расширение
/api/v1/getOrders ✗ — глагол
Служебные эндпоинты — вне /api/v1:
/health— работоспособность./ready— готовность принимать трафик (K8s readiness)./info— метаинформация./metrics— Prometheus / Micrometer.
Не требуют аутентификации (или защищены через management-port). Не версионируются.
Ресурсы
R-RES-1..3:
/orders ✓ коллекция (множественное)
/orders/{id} ✓ один заказ
/users/{id}/profile ✓ singleton (один на пользователя)
/settings ✓ глобальные настройки
/order ✗ единственное для коллекции
/orders/{id}/item ✗ микс единственного и множественного
Имя ресурса = доменный термин из Ubiquitous Language:
Order→/orders, не/purchases,/transactions.OrderItem→/items(вложенный), не/lines,/rows.DeliveryAddress→/delivery-addresses, не/addresses,/shipping-info.Payment→/payments, не/charges,/billing.
Это даёт трассируемость между кодом, спецификацией и API.
HTTP-методы
R-MTH-1..6: семантика.
| Метод | Что | Идемпотентный | Success codes | Error codes |
|---|---|---|---|---|
GET | чтение | да | 200 | 404 |
POST | создание / команда | нет | 201 + Location / 202 | 400 |
PUT | полная замена | да | 200 | 400, 404 |
PATCH | частичное обновление (JSON Merge Patch RFC 7396) | да-на-практике | 200 | 400, 404 |
DELETE | удаление | да | 204 | 404 |
@PostMapping("/orders/{id}/cancel") ✓ POST для команды с side-effect
public OrderResponse cancel(@PathVariable Long id) { ... }
@GetMapping("/orders/{id}/cancel") ✗ GET с побочным эффектом
public OrderResponse cancel(@PathVariable Long id) { ... }
Полный перечень допустимых кодов ошибок — Ошибки RFC 9457.
Вложенность
R-NEST-1..4:
/orders/{id} ✓ 1 уровень
/orders/{id}/items ✓ 2 уровня
/orders/{id}/items/{id} ✓ 2 уровня + id
/users/{id}/orders/{id}/items/{id} ✗ 3 уровня
Глубже двух уровней — flat resource с filter:
/items?orderId={id} ✓ вместо /orders/{id}/items
Принцип: дочерний ресурс не существует вне родителя (OrderItem без Order бессмыслен) — допустима вложенность; иначе — flat с filter.
Path-переменная всегда {id}
В дизайне URL path-переменная для идентификатора — всегда {id}. Контекст (имя ресурса в предыдущем сегменте) устраняет неоднозначность:
/orders/{id} ✓
/orders/{id}/items/{id} ✓ — первый = order, второй = item
ID в теле запроса — запрещён:
PUT /orders/{id} ✓ id из пути
PUT /orders { "id": ... } ✗ id в body
Двойной стандарт с OpenAPI
В спецификации OpenAPI параметры пути обязаны быть уникально именованы (orderId, itemId) — это требование Swagger/Redoc. Подробнее — OpenAPI и антипаттерны, правило R-OAS-3.
Что запрещено
| Антипаттерн | Правило | Что взамен |
|---|---|---|
HATEOAS _links в теле ответа | R-PRIN-X1 | OpenAPI описывает навигацию |
/OrderItems (заглавные) | R-URL-X1 | /order-items |
/orders/ (trailing slash) | R-URL-X2 | без слеша |
/orders.json | R-URL-X3 | Accept: application/json |
/getOrders, /createOrder (глаголы) | R-URL-X4 | GET /orders, POST /orders |
/order для коллекции | R-RES-X1 | /orders |
/order/{id}/items микс единственного и множественного | R-RES-X2 | /orders/{id}/items |
GET /orders/{id}/cancel (side-effect через GET) | R-MTH-X1 | POST /orders/{id}/cancel |
| 3 уровня вложенности | R-NEST-X1 | flat с filter |
| ID в body вместо path | R-NEST-X2 | path-параметр |
{orderId} в URL дизайне (когда контекст задан) | R-NEST-X3 | {id} |
Куда дальше
- REST API → URL и ресурсы (нормативно) — формулировки.
- Alias и Action-эндпоинты —
me,latest, доменные команды. - Версионирование и breaking changes —
v1/v2в URL. - Query-параметры и пагинация — фильтры.
- OpenAPI и антипаттерны —
R-OAS-3именование path-параметров. - DDD → ubiquitous language — имя ресурса = доменный термин.