Как правильно именовать REST endpoints?
Именование эндпоинтов — это создание понятного и предсказуемого API.
Junior Level
Именование эндпоинтов — это создание понятного и предсказуемого API.
Основные правила:
- Используйте существительные, а не глаголы:
- ✅
GET /users/1 - ❌
GET /getUser/1
- ✅
- Используйте множественное число:
- ✅
/users,/orders,/products - ❌
/user,/order,/product
- ✅
- Используйте kebab-case:
- ✅
/audit-logs,/user-profiles - ❌
/audit_logs,/userProfiles
- ✅
- Используйте нижний регистр:
- ✅
/users/active - ❌
/Users/Active
- ✅
Примеры:
GET /users — получить всех пользователей
GET /users/1 — получить пользователя с ID 1
POST /users — создать пользователя
GET /users/1/orders — получить заказы пользователя
GET /users?role=admin — отфильтровать пользователей по роли
Фильтрация и поиск:
- ✅
/users?role=admin&status=active— параметры запроса - ❌
/users/role/admin— не делайте URI иерархичным там, где иерархии нет
Middle Level
Senior-правила именования:
- Множественное число:
/usersпредставляет коллекцию,/users/1— элемент коллекции - Kebab-case: Дефис — стандарт для URL (RFC 3986), лучше воспринимается поисковиками
- Нижний регистр: URL чувствительны к регистру на некоторых серверах (Linux/Nginx)
Как быть с действиями (Actions)?
Если действие не укладывается в CRUD (например, “активировать пользователя”):
- Resource-oriented (лучший):
PATCH /users/1с телом{"status": "ACTIVE"} - Sub-resource:
POST /users/1/activation— создаём “сущность активации” - Controller-style (допустимо):
POST /users/1/activate— для сложных команд
Поиск и фильтрация
- ✅
/users?role=admin— Query Params для фильтрации - ❌
/users/role/admin— URI не должен быть иерархичным без иерархии
“Search-only” эндпоинты
В системах вроде Elasticsearch используют префикс _: POST /users/_search. Это помогает избежать коллизий с ID ресурсов.
Пограничные случаи
- Trailing Slash:
/users/и/users— два разных ресурса. НастройтеStrictTrailingSlashPatternMatch. По умолчанию Spring Boot 3+ делает 308 redirect с/users/на/users. Если это нежелательно, настройтеuseTrailingSlashMatchв конфигурации. - ID в пути vs в заголовке: Как правило, не передавайте ID текущего пользователя в пути, если он уже есть в JWT. Используйте
/users/me/profile. Исключение — административные эндпоинты, где админ работает с чужим ID. Это предотвращает IDOR (Insecure Direct Object Reference) атаки.- IDOR (Insecure Direct Object Reference) — атака, при которой злоумышленник подменяет ID в URL (
/users/123→/users/124), получая доступ к чужим данным. Защита: сверять ID из URL с ID в JWT.
- IDOR (Insecure Direct Object Reference) — атака, при которой злоумышленник подменяет ID в URL (
Диагностика
- 404 vs 405: Если ресурс существует, но метод не подходит — вернуть 405 Method Not Allowed с заголовком
Allow, а не 404 - URI Length: Браузеры и прокси ограничивают длину URL (2048 или 8192 символа). При слишком многих фильтрах — переходите на
POST /_search
Senior Level
Сложные сценарии именования
Matrix Parameters
Редко используемая возможность URL;param=value (например, /users;status=active/orders). Spring MVC поддерживает через @MatrixVariable. Полезны для передачи параметров в середину пути.
IDOR Prevention
Как правило, не передавайте ID текущего пользователя в пути, если он уже есть в JWT. Используйте /users/me/profile — это предотвращает Insecure Direct Object Reference атаки.
- IDOR (Insecure Direct Object Reference) — атака, при которой злоумышленник подменяет ID в URL (
/users/123→/users/124), получая доступ к чужим данным. Защита: сверять ID из URL с ID в JWT.
Производительность и Инфраструктура
- URI Length Limit: Браузеры и прокси ограничивают длину URL. При слишком большом количестве фильтров — переходите с
GETнаPOST /_search - Matrix Parameters: Spring MVC поддерживает
@MatrixVariableдля передачи параметров в середину пути
API Discovery
Хорошо спроектированное API позволяет вызвать OPTIONS /users и получить список доступных методов и параметров. Это позволяет клиентам динамически обнаруживать возможности API.
Edge Cases
- Если ресурс
/users/1существует, но вы вызвалиPOSTвместоGET— сервер должен вернуть 405 Method Not Allowed с заголовкомAllow: GET, PUT, DELETE. Возврат404— ошибка дизайна - При интеграции с внешними системами документируйте все возможные query-параметры
🎯 Шпаргалка для интервью
Обязательно знать:
- URI — существительное во множественном числе:
/users,/orders,/products - Kebab-case для URL:
/audit-logs,/user-profiles(RFC 3986) - Фильтрация через query-параметры:
/users?role=admin&status=active, не через иерархию URI - Actions не-CRUD:
PATCH /users/1с телом илиPOST /users/1/cancellation(resource-as-action) - Trailing Slash:
/users/и/users— разные ресурсы; Spring Boot 3 делает 308 redirect - IDOR Prevention: использовать
/users/me/profileвместо/users/{id}/profile, если ID уже в JWT - 405 Method Not Allowed с заголовком Allow — правильный ответ, если метод не подходит (не 404)
Частые уточняющие вопросы:
- Как обрабатывать действия вроде «активировать»? — PATCH с
{"status": "ACTIVE"}или POST /users/1/activation - Что такое IDOR и как защититься? — Подмена ID в URL; защита: сверять ID из URL с ID в JWT
- Когда использовать POST /_search вместо GET? — При слишком большом количестве фильтров (URL > 2048 символов)
- Что такое Matrix Parameters? — Редко используемые
URL;param=value, поддерживаются через @MatrixVariable в Spring
Красные флаги (НЕ говорить):
- «Глаголы в URL — это нормально» — URI = существительное, действие = HTTP метод
- «404 — правильный ответ для неподходящего метода» — нужен 405 Method Not Allowed с заголовком Allow
- «Единственное число лучше множественного» — множественное число — стандарт индустрии
audit_logsилиuserProfilesв URL» — kebab-case (audit-logs) — стандарт для URL
Связанные темы:
- [[Что такое RESTful API дизайн]]
- [[Стоит ли использовать глаголы в URL]]
- [[Какие основные HTTP методы используются в REST]]
- [[В чём разница между 401 и 403]]
- [[Как организовать версионирование REST API]]