Опирается на правила: 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 codesError codes
GETчтениеда200404
POSTсоздание / команданет201 + Location / 202400
PUTполная заменада200400, 404
PATCHчастичное обновление (JSON Merge Patch RFC 7396)да-на-практике200400, 404
DELETEудалениеда204404
@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-X1OpenAPI описывает навигацию
/OrderItems (заглавные)R-URL-X1/order-items
/orders/ (trailing slash)R-URL-X2без слеша
/orders.jsonR-URL-X3Accept: application/json
/getOrders, /createOrder (глаголы)R-URL-X4GET /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-X1POST /orders/{id}/cancel
3 уровня вложенностиR-NEST-X1flat с filter
ID в body вместо pathR-NEST-X2path-параметр
{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 — имя ресурса = доменный термин.