У всіх підручниках в описах REST дають прості приклади, типу ось вам користувачі, вони будуть ресурсом/users, ось вам один користувач, він буде/users/[ id] і дії з ним додати\вилучити\змінити.
А що якщо дії складні або комплексні і не вписуються в GET\POST\DELETE?
Намагаючись розібратися, поставив питання на тостері і продовжив подальші розкопки.
Знайшов вичерпну статтю, але повний переклад не осиллю, так що зведу зроблені висновки в коротку замітку.
Коротко про проблему:
Головна відмінність REST від RPC полягає в підході, що URL - адреса ресурсу, дії з яким виконуються за допомогою стандартних HTTP-методів: GET\POST\DELETE\PATCH\… Якщо коротко - ресурс це існуюче, а не дієслово.
Тобто. якщо ви бачите щось типу/ api/users/do_some_cool_staff або GET/users/1? action = delete, знайте - це не REST!
Припустимо, ми пишемо додаток «ядерна валізка» з REST інтерфейсом. Функціонал буде такий:
1. Дії з ракетою [id]: запуск по країні, продаж в країну, обслуговування, списати в утиль
Логічно використовувати ресурс/missiles/[ id], але для цих дій просто використовувати PUT або PATCH некоректно і неінформативно.
Неправильні варіанти:
1. Можна розширяти список стандартних HTTP-методів. Але можуть бути складнощі з підтримкою різних клієнтів, готових бібліотек і фільтрування налаштувань сервера.
2 ./missiles/[ id]? action = launch позбавляє значення весь REST підхід, оскільки більша частина функціоналу буде в діях.
3 ./missiles/[ id ]/launch - тягнути дієслово на адресу ресурсу неправильно.
4. LINK/missiles/[ id ]/countries/[ country _ id ]/- незрозуміло що саме відбувається - продаж або ядерний удар.
Правильний варіант
Правильно звертатися до властивостей ресурсу. Тобто. не дія «»/users/[ id ]/disable« », а ресурс« »/users/[ id ]/disabled «», до якого логічно застосовні стандартні методи GET\POST\...
Запуск ракети: POST /missiles/[id]/countries-landed/[country_id]
Продаж ракети: POST /countries/[country_id]/missiles-bought/[id] или POST /missiles/[id]/owner/[country_id]
Обслуговування: POST /missiles/[id]/on-service
UPD:
Запуск ракети: POST /missiles/[id]/launcher {target: [country_id]}
Продаж ракети: PATCH /missiles/[id] {owner: [country_id]}
Обслуговування: PUT/missiles/[ id ]/on-service або якщо є окремий сервіс обслуговування ракет POST/ missiles_service/ {missile: [id]}
Списати в утиль: DELETE/missiles/[ id] або якщо можуть бути інші варіанти «вилучення» PUT/missiles/[ id ]/utilized
2. Запустити будь-яку відповідну ракету по країні [country_id]
Припустимо, що ракет дуже дофіга і робити спочатку пошук, а потім запуск накладно і довго, потрібен один запит на моментальне виконання.
Неправильні варіанти:
1. Виконати «запуск» на всю колекцію ракет ([id] конкретної ракети ми не знаємо).
2. Дію «отримати ракетою» у обраної країни
Правильний варіант
Якщо дія комплексна і не може бути виражена через атомарні дії над ресурсом-об'єктом, створюється ресурс-процес. Аналогічно ресурс-процес створюється у разі, якщо потрібно зробити складову дію зі складною бізнес-логікою (що складається з декількох залежних дій), наприклад банківська транзакція.
Думка більш розгорнута
Let us relook at what Roy Fielding’s dissertation says about resource: “...any concept that might be the target of an author's hypertext reference must fit within the definition of a resource….”. Business capabilities / processes can neatly fit the definition of resources. In other words, for complex business processes spanning multiple resources, we can consider the business process as a resource itself. For example, the process of setting up a new customer in a banking domain can be modeled as a resource. CRUD is just a minimal business process applicable to almost any resource. This allows us to model business processes as true resources which can be tracked in their own right.
Тобто. правильним буде створення ресурсу «Запуск ракети».
Тоді POST буде запускати ракету, GET дізнаватиметься стан процесу, DELETE скасовуватиме його. При цьому зберігається консистентність, тобто ракета вже летить, а статус країни «ще існує».
Бонусом:
Виявилося, що багато великих компаній взагалі не мають уявлення, що таке REST, при цьому в описі використовують саме цю назву. Тож не можна довіряти всьому, що написано на паркані навіть у крупняків.
Пара прикладів ахтунгів:
POST friendships/create
POST friendships/destroy
POST friendships/update
GET friendships/show
GET friends/list
- ru
Всі виклики методів API - це GET або POST HTTP-запити до URL www.appsmail.ru/platform/api з деяким набором параметрів. [...] На даний момент, API не робить відмінностей між GET- і POST-запитами.
Єдине пристойне REST API, яке я зміг виявити GitHub. Амінь.
