REST: проектирование URL

Проектирование URL в REST — набор соглашений об именовании эндпоинтов, обеспечивающих единообразие, читаемость и предсказуемость API.

Зачем нужно

Предсказуемые URL снижают когнитивную нагрузку на разработчиков-клиентов API: зная паттерн /api/users/42/posts, можно догадаться об остальных эндпоинтах без документации. Консистентность URL облегчает поддержку, тестирование и версионирование.

Где используется

  • Разработка REST API на любом стеке (Express, Fastify, Django, Rails)
  • Код-ревью и архитектурные решения
  • Документирование API в OpenAPI/Swagger
  • Публичные API, рассчитанные на внешних разработчиков

Основные правила

Существительные, не глаголы

✅ Правильно                    ❌ Неправильно
GET    /api/users               GET /api/getUsers
POST   /api/users               POST /api/createUser
GET    /api/users/42            GET /api/getUserById?id=42
DELETE /api/users/42            POST /api/deleteUser/42
PATCH  /api/users/42            POST /api/users/42/update

Множественное число для коллекций

/api/users          — коллекция пользователей
/api/users/42       — конкретный пользователь
/api/articles       — коллекция статей
/api/articles/slug  — статья по slug

Вложенные ресурсы (отношения)

GET /api/users/42/posts         — посты пользователя 42
POST /api/users/42/posts        — создать пост от пользователя 42
GET /api/posts/7/comments       — комментарии к посту 7
DELETE /api/posts/7/comments/3  — удалить комментарий 3 из поста 7

# Не глубже 2-3 уровней вложенности
❌ /api/users/42/posts/7/comments/3/likes
✅ /api/comments/3/likes

Query-параметры для фильтрации, сортировки, пагинации

# Фильтрация
GET /api/users?role=admin&status=active

# Сортировка (- означает убывание)
GET /api/products?sort=-price,name

# Пагинация
GET /api/users?page=2&limit=20
GET /api/users?offset=40&limit=20
GET /api/users?cursor=eyJpZCI6NDB9  # cursor-based

# Выбор полей (sparse fieldsets)
GET /api/users?fields=id,name,email

# Поиск
GET /api/products?search=ноутбук

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

# Вариант 1: Префикс версии (наиболее распространённый)
/api/v1/users
/api/v2/users

# Вариант 2: Заголовок (чище, но сложнее для клиентов)
GET /api/users
Accept: application/vnd.myapp.v2+json

# Вариант 3: Query (не рекомендуется — засоряет логи)
GET /api/users?version=2

Специальные действия (нон-CRUD операции)

# Когда действие не вписывается в CRUD — используем глагол-суффикс
POST /api/orders/42/cancel
POST /api/users/42/verify-email
POST /api/payments/42/refund
POST /api/reports/generate

# Или глагол через resource: actions
POST /api/users/42/actions/promote-to-admin

Формат URL

✅ kebab-case для сегментов:
   /api/user-profiles/42
   /api/blog-posts

❌ camelCase, snake_case в URL:
   /api/userProfiles/42
   /api/blog_posts

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

  • Глаголы в URL: /api/createOrder — нарушает принцип Uniform Interface
  • Смешение единственного и множественного числа: /user/42 vs /users
  • Слишком глубокая вложенность: /a/b/c/d/e — трудно читать и маршрутизировать
  • Значимые данные в пути вместо query-параметров: /api/users/active/admin вместо ?status=active&role=admin

Связанные темы

Ресурсы