Действия/службы RESTful, которые не соответствуют объекту?
Мне нравится RESTful за его простоту и то, как он избегает крутизны обычных "корпоративных" систем, таких как SOAP, или двоичной твердости DCOM и RPC.
Но REST больше подходит для объектов базы данных, чем для более абстрактных служб. Мне было интересно, можете ли вы посоветовать мне, как бы вы это делали:
Например, предположим, что у меня есть веб-сервис RESTful для нормальной системы баз данных (например, сайт для покупки молочных продуктов), поэтому у меня есть/продукты/яйца/батарея и/продукты/молоко/снятое
Выполнение INSERT будет достигнуто путем создания POST в /products/eggs.
Но как бы вы сделали команду "очистить все"? Глагол DELETE подходит только для отдельных объектов. И "DELETE/products/milk" подразумевает удаление самой категории продукта "молоко", а не только всех продуктов в категории "молоко". И что, если вы хотите выполнить оба?
Другой вопрос, который я имею в отношении действий веб-сервиса, которые не связаны с сущностью. Например, если я создаю веб-сервис для базы данных паролей, у меня бы были такие операции, как "GET/passwords/stackoverflow.com", что было бы неплохо, но у меня также были бы операции по отключению веб-сайта в случае вторжения обнаружение. В рамках модели веб-сервиса "старой школы" у меня был бы метод, называемый "disableWebsite", однако я не могу создать HTTP-глагол под названием "DISABLE" и ресурс под названием "/website" (так что запрос будет "DISABLE/website" ). Какое решение здесь?
Наконец, как вы скомбинируете HTML-формы с RESTful? Веб-формы могут обрабатывать запросы GET только с помощью запросов или POST. Если у меня есть форма поиска, я хочу, чтобы он запрашивал "/products/search/{query}", но прямо сейчас запрос будет выглядеть как "/products/search? Query = {query}".
Ответы
Ответ 1
Я думаю, вы должны перестать думать о ресурсах как синонимы для объектов базы данных. Да, они часто связаны между собой, но ресурс - это всего лишь адресная концепция вашего домена. Я думаю, что гораздо полезнее думать о ресурсах, как о вещах, которые вы видите в Интернете, когда используете свой браузер (списки, элементы, сообщения, комментарии, изображения и т.д.).
Но как бы вы выполнили команду "очистить все"?
Я не уверен, почему DELETE/products/milk подразумевает удаление самой молочной категории, но если вы предпочтете:
DELETE /products?category=milk
DELETE не означает удаление одного объекта базы данных. Это подразумевает удаление одного ресурса. И "/products? Category = milk" (или "/products/milk", если на то пошло) идентифицирует единственный ресурс. Если вы можете получить его, вы можете УДАЛИТЬ его.
А что, если вы хотите выполнить оба?
Как насчет этого?
DELETE /product-categories/milk
Один трюк, который стал популярным в Ruby on Rails, - это предоставить форму (используя GET) для любой операции PUT/POST/DELETE. Таким образом, для этих удалений вы можете предоставить такую форму:
GET /product-categories/milk/delete
В этой форме (думаю, HTML) вы могли бы спросить у вашего пользователя, действительно ли удастся удалить всю категорию. (Пожалуйста, не обращайте внимания на то, что HTML-формы на самом деле не совместимы с веб-службами RESTful. является довольно успешным форматом для взаимодействия с ресурсами в Интернете, и хорошо разработанное приложение AJAX, вероятно, сначала работает как хорошо разработанное приложение HTML. Есть некоторые детали, которые необходимо разработать для поддержки как браузеров, так и ваших других клиентов, но все они являются законными клиентами REST.)
Как отключить веб-сайт?
Есть много способов сделать это. Только PUT для /sites/stackoverflow.com с флагом для отключения может работать.
Наконец, как вы скомбинируете HTML-формы с RESTful?
Вы действительно не можете выполнить HTTP PUT или DELETE из браузера, но вы можете предоставить скрытое поле в своей форме, чтобы подделать его:
<input type="hidden" name="_method" value="PUT" />
Пока ваш механизм маршрутизации поддерживает его, это хороший способ маршрутизации сообщения браузера соответствующему обработчику (я также видел, что люди используют заголовок X-HTTP-Method-Override для не-HTML-клиентов без полного поддержка HTTP-глаголов).
Если вы заинтересовались копанием, я рекомендую Cookbook Web Services в качестве стартера. Кроме того, взгляните на модель зрелости Ричардсона. И помните, что REST похож на остальную часть Интернета. Это было бы не очень полезно без ссылок. Предоставьте своим клиентам возможность обойти.
<a href="/products/milk/delete" rel="delete" />
<atom:link href="/products/milk/delete" rel="delete" />
Ответ 2
Системы RESTful взаимодействуют с "ресурсами", которые не коррелируют со стандартным понятием сущности.
"Ресурс" - это очень нечеткая концепция с несколькими строгими правилами. Мне нравится думать о ресурсе как о любой полезной концепции, которая может помочь в том, чтобы позволить клиенту делать то, что им нужно делать.
Итак, если вам нужно удалить кучу сущностей, тогда создайте ресурс, который представляет эту "группу сущностей", а затем используйте метод DELETE на нем.
Реальным трюком для создания систем отдыха является прекращение попытки присвоить значение конкретным ресурсам, но присвоить значение отношениям между двумя ресурсами. Подумайте о том, как работает HTML. Вы загружаете страницу, и есть ссылка на таблицу стилей. rel= "stylesheet" определяет значение того, что вы находите в конце URL-адреса href.
Если вы хотите отключить веб-сайт, обратитесь к ресурсу веб-сайта и используйте URL-адрес, который находится в ссылке с rel= "disabler". Проект RESTful посвящен определению ресурсов, которые взаимосвязаны по ссылкам. Некоторые ссылки используются только для извлечения информации, другие фактически используются для внесения изменений в состояние ресурса.
Строгие правила, которым должен следовать ресурс, заключаются в том, что ресурс должен иметь идентификатор (например, URL-адрес), и вы можете взаимодействовать только с этим ресурсом через "представления" этого ресурса. Эти представления могут быть представлены в самых разных форматах.
Что касается HTML-форм, забыть о том, что выглядит URI, то параметры строки запроса так же, как RESTful, как параметры пути. HTML-формы позволяют делать GET и POST, т.е. Безопасные операции и небезопасные операции. Этого достаточно для любого, кто сделает REST. Конечно, DELETE и PUT могут быть полезны, но на самом деле преимущества, которые эти дополнительные методы привносят в систему RESTful, очень малы, по сравнению с чем-то вроде гипермедиа.
Ответ 3
Но как бы вы сделали команду "очистить все"? Глагол DELETE подходит только для отдельных объектов.
False.
И "DELETE/products/milk" подразумевает удаление самой категории продукта "молоко", а не только всех продуктов в категории молока.
Правильно.
А что, если вы хотите выполнить оба?
Что случилось с DELETE на /cart/milk/
?
В рамках модели веб-сервиса "старой школы" у меня был бы метод, просто названный "disableWebsite",
Что?
однако я не могу создать HTTP-глагол под названием "DISABLE" и ресурс под названием "/website" (так что запрос будет "DISABLE/website" ). Какое решение здесь?
POST. POST до /passwords/stackoverflow.com/disable/
Объект (passwords/stackoverflow.com
) содержит внутри него субобъект "disable" и "enable". Вы можете отправить сообщение в любой из них, чтобы изменить состояние родительского объекта.
Если у меня есть форма поиска, я хочу, чтобы он запрашивал "/products/search/{query}"
Вот почему большинство веб-служб RESTful написаны в Javascript или Flex или что-то в этом роде.
Веб-службы RESTful и "родные" HTML-формы на самом деле не совместимы. Они не должны быть.