Как правильно именовать сложные действия в REST API?

Добрый день!

Во всех руководствах в описаниях REST дают простые примеры, типа вот вам пользователи, они будут ресурсом /users, вот вам один пользователь, он будет /users/[id] и действия с ним добавить\удалить\изменить.

Предположим, пишем приложение "ядерный чемоданчик" с REST интерфейсом. Функционал:
1. Действия с ракетой [id]: запуск по стране, продажа в страну, обслуживание, списать в утиль
По смыслу используемый ресурс /missiles/[id], но указанные действия "в лоб" ни в один из стандартных HTTP методов не вписываются.

Есть вариант расширять список стандартных HTTP-методов, но какой-то он идеологически не правильный. Плюс могут быть сложности с поддержкой у разных клиентов и готовых библиотек.

Делать /missiles/[id]?action=launch лишает смысла весь REST подход, т.к. бОльшая часть функционала будет в действиях.

Делать /missiles/[id]/launch - тащим глагол в адрес ресурса - тоже неправильно.

2. Запустить ракету [id] по стране [country_id].
С некоторой долей юмора можно сделать PATCH или LINK /missile/[id]/country/[id], но это разовое действие, а не постоянная связь.
Опять же, есть несколько похожих действий (продать в страну или запустить по стране), т.е. будет неочевидно что из них что ну и количество стандартных методов ограничено.
Можно сделать действие "быть раздолбанным" для ресурса /countries/[id], но это по смыслу бредово.

3. Запустить любую подходящую ракету по стране [country_id].
Предположим, что ракет очень дофига и делать сначала поиск, а потом запуск накладно и долго, нужен один запрос на моментальное исполнение.
Смысл что [id] конкретной ракеты мы не знаем, выполнять действие "запуск" на всю коллекцию ракет некорректно.

4. Действия не имеющие ресурса
Есть например действие "провести парад". Никаких связанных ресурсов нет, только глагол.
Тащить его в URL /start_parade ?
  • Вопрос задан
  • 8260 просмотров
Решения вопроса 1
azverin
@azverin Автор вопроса
По результатам раскопок и сделанных выводов опубликовал статью: habrahabr.ru/post/251193
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 4
@napa3um
В идеологии REST нужно мыслить с точки зрения декомпозиции предметной области задачи на объекты-ресурсы (с соответствующими урлам), а глаголы (действия) строго фиксированные (закреплённые, в том числе, в протоколе HTTP). Этим достигается масштабируемость (во всех смыслах) разрабатываемого веб-сервиса. Если в прикладной области видится большое разнообразие действий, а не объектов, то их можно воспринимать в стиле документов документооборота или транзакций платёжной системы. Например, пуск ракеты по стране можно представить в виде создания документа (транзакции) "пуск ракеты по стране". Оформить можно и как вложенный в ракету ресурс, и как корневой ресурс с атрибутами "ракета" и "страна", - это зависит от физической и логической организации сервиса. Такой ресурс-документ можно снабдить идентификатором и дать ему возможность обрабатываться на любом сервере, входящем в инфраструктуру веб-сервиса, читать из него автоматически сгенерированные атрибуты типа "время запуска", "статус полёта", т.п. В общем, основная идея комментария: мыслить в терминах документооборота, и сервис получится логичным, поддерживаемым, масштабируемым, как и задумано REST'ом.
Ответ написан
Комментировать
GM2mars
@GM2mars
Много где читал, да и сам придерживаюсь использовать в нестандартных запросах - параметры.
Опять же нужно определить основной ресурс с которым идет работа, в вашем примере скорее всего это ракета.
У этого ресурса может быть состояние или действие (зависит от архитектуры, что лучше подходит).
Пример с ракетой у которой меняем состояние: (В этом случае у таблицы с ракетами должно быть поле target)
PUT rocket/23/?launch {'target': 'usa'}

Пример с действиями подразумевает более широкие возможности по использованию ракет. В данном примере должна быть отдельная таблица rocket_action с полями: действие, состояние, цель ...
Запрос на продажу ракеты:
POST rocket/23/?sale {'target': 'pakistan', 'price': 235000};
(соответственно контроллер, который отвечает за обработку этого действия должен удалить ракету из таблицы ракет или изменить её состояние)

Что же касается действий под пунктами 3 и 4:
3 - Такие действия должны лучше разбивать на поддействия: 1. запросить какая ракета свободна (или ближе всех к этой стране) 2. запустить эту ракету в страну.
4 - думаю что тут нужно пересматривать архитектуру приложения, если нет сущности, с которым мы можем выполнять действие. Для вашего примера лучше подойдет выделение отдельной ракеты для парада POST rocket/23/?start_parad {'place': 'Moscow'}

Да и вообще REST это довольно абстрактная архитектура. Тут в первую очередь нужно думать о том, что хочет получить пользователь отправляя этот запрос, а уже потом на сколько он логичен в техническом плане построенной архитектуры.
Ответ написан
DmitriyEntelis
@DmitriyEntelis
Думаю за деньги
Все imho
1) POST /missiles/[id]/launch мне кажется вполне нормальным
2) POST /missile/[id]/country/[id] мне кажется вполне нормальным
3) POST /country/[id]/destroy ;)
4) POST /parade/start
Ответ написан
Комментировать
FanatPHP
@FanatPHP
Чебуратор тега РНР
По-моему, у тебя в голове перемешались методы НТТР и имена методов в адресе.
иначе я не могу объяснить фразу
По смыслу ресурс /missiles/[id], но действия ни в один из стандартных HTTP методов не вписываются.

Что такого необычного в имени REST метода "missiles" - я не понимаю
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы