Питання 12 · Розділ 6

Як правильно іменувати REST endpoints?

Іменування ендпоінтів — це створення зрозумілого і передбачуваного API.

Мовні версії: English Russian Ukrainian

Junior Level

Іменування ендпоінтів — це створення зрозумілого і передбачуваного API.

Основні правила:

  1. Використовуйте іменники, а не дієслова:
    • GET /users/1
    • GET /getUser/1
  2. Використовуйте множину:
    • /users, /orders, /products
    • /user, /order, /product
  3. Використовуйте kebab-case:
    • /audit-logs, /user-profiles
    • /audit_logs, /userProfiles
  4. Використовуйте нижній регістр:
    • /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 (наприклад, “активувати користувача”):

  1. Resource-oriented (найкращий): PATCH /users/1 з тілом {"status": "ACTIVE"}
  2. Sub-resource: POST /users/1/activation — створюємо “сутність активації”
  3. 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.

Діагностика

  • 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]]