Как должна выглядеть схема REST URL для древовидной иерархии? - PullRequest
26 голосов
/ 27 января 2010

Давайте предположим, что у меня есть магазины, полки в магазине и продукты на полке. Поэтому, чтобы получить список товаров на полке в магазине, я бы использовал следующий запрос:

GET http://server/stores/123/shelves/456/products

Как я могу получить отдельный продукт? Должен ли я использовать:

GET http://server/products/789

Или:

GET http://server/stores/123/shelves/456/products/789

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

Аналогично, как насчет операции PUT / DELETE?

DELETE http://server/stores/123/shelves/456/products/789

Или:

DELETE http://server/products/789

Каков будет правильный способ создания схемы для такой древовидной иерархии?

P.S. Если я что-то неправильно понимаю в архитектуре REST, приведите примеры того, как я могу сделать это лучше. Слишком много людей, которые любят говорить «REST - это не CRUD» и «REST - это не RPC», не дают абсолютно никаких разъяснений или примеров хорошего дизайна RESTful.

Ответы [ 5 ]

17 голосов
/ 19 октября 2013

Я отметил 2 подхода к разработке RESTful URI: иерархический и отфильтрованный

Я чувствую, что иерархическая структура является слишком многословной, имеет потенциал для избыточных конечных точек (не СУХОЙ) и маскирует то, в каком состоянии ресурса вы действительно заинтересованы (в конце концов, REST = репрезентативная передача состояния).

Я предпочитаю простые URI

Просто элегантно. Я бы выбрал структуру URI, такую ​​как

GET http://server/products/789

потому что меня интересует состояние ресурса продукта.

Если бы я хотел, чтобы все товары, которые принадлежали определенной полке в конкретном магазине, я бы сделал

GET http://server/products?store=123&shelf=456

Если бы я хотел создать продукт в определенном магазине на определенной полке, то я бы опубликовал

{
    product: {
        store: 123,
        shelf: 456,
        name: "test product"
    }
}
* * Тысяча двадцать-одина с помощью * * тысяча двадцать две
POST http://server/products

В конце концов, это томайто, томахто

REST не требует одного над другим. Однако, по моему собственному опыту, более эффективно использовать RESTful API, который отображает отдельные сущности на отдельные конечные точки (например, сопоставления объектов RestKit на iOS), вместо того, чтобы сопоставлять сущности множеству разных конечных точек в зависимости от того, какие параметры передаются.

О ОТДЫХЕ

Что касается REST, то он не является протоколом и не имеет RFC. Он тесно связан с RFC HTTP / 1.1 как способом реализации своих действий CRUD, но многие разработчики программного обеспечения утверждают, что REST не зависит от HTTP. Я не согласен и считаю это предположением, потому что оригинальная диссертация Роя Филдинга (UCI) (http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm) объясняет глубоко укоренившуюся связь REST и HTTP / 1.1. Вам также может понравиться мнение Роя по этой теме: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven.

Принципы, определенные REST, могут применяться к другим протоколам, но REST был создан для Интернета, а HTTP - это протокол для всемирной паутины.

REST vs RPC

RPC предназначен для вызовов удаленных функций и является глагол-центрированным .

REST - это использование соглашения CRUD для обработки данных в зависимости от того, как операция CRUD применяется к данному типу данных, и существительное-центрированное .

Вы можете выполнить то же самое с помощью REST или RPC, но REST следует принципам DRY, потому что для каждого URI вы можете выполнить 4 действия, тогда как RPC требует конечную точку для каждого действия.

PS

Многое из этого является моим мнением и основано на моем опыте, но я надеюсь, что это проливает некоторый свет на то, как вы могли бы наиболее эффективно разработать схему RESTful URI. Как всегда, ваши конкретные цели и потребности будут влиять на ваш выбор, но простота - всегда хорошая цель для достижения цели.

6 голосов
/ 21 февраля 2013

Создание продукта должно быть просто POST до

http://server/product

Обновление продукта должно быть просто PUT до

http://server/product/$id

Получение продукта должно быть просто ПОЛУЧИТЬ

http://server/product/$id

Удаление продукта должно быть просто УДАЛИТЬ до

http://server/product/$id

Вы должны использовать имеющиеся здесь методы http, чтобы получить больше функциональности от более простой структуры URI. Если создание продукта требует передачи в магазине и на полке в качестве требования, то они должны быть переданы в теле вашего POST (или PUT, если вы меняете полки).

Когда кто-то делает GET для http://server/product/$id, он получит какой-то ответ xml / json, верно? На что это похоже? Входящие данные для создания или обновления должны быть POSTed или PUT таким же образом в теле запроса. Вот так вы проходите в магазине и на полке, а не через ури. URI должен быть максимально простым и просто указывать на ресурс (продукт), используя глаголы http для разграничения функциональности.

Если вы хотите получить содержимое полки 23, выполните GET для

http://server/shelf/23

Когда вы это сделаете, вы получите обратно документ json / xml / custom media type, содержащий данные полки и коллекцию элементов продукта со ссылками на их URI продукта.

Если вы хотите иметь возможность перемещать продукт 23 с одной полки на другую, вы делаете PUT на

http://server/product/23 

В корпусе PUT у вас есть продукт в представлении по вашему выбору, но с обновленной полкой.

Сначала это странный способ мышления, потому что вы не имеете дело с функциональностью всей системы, а вместо этого сосредотачиваетесь на ресурсах (продукт, полка, хранилище) и используете глаголы http, чтобы представить их вселенной.

2 голосов
/ 28 января 2010

Не создавайте API REST на основе структуры URL. Здесь - вот, как я думаю, вам следует заняться разработкой REST API.

Попытка определить интерфейс REST без обсуждения того, какие ссылки будут содержаться в каких ресурсах, как обсуждение интерфейса RPC и игнорирование параметров и возвращаемых значений.

2 голосов
/ 27 января 2010

Поскольку товары могут находиться в нескольких магазинах или на нескольких полках (категориях?), У каждого продукта должен быть уникальный номер независимо от его положения в иерархии. Затем используйте плоский номер продукта. Это делает API более стабильным, например, когда некоторые товары перемещаются в ваш магазин.

Короче говоря, не добавляйте ненужную избыточность в ваш API. Для получения списка полок достаточно идентификатора магазина, для списка продуктов достаточно идентификатора полки ... и т. Д.

0 голосов
/ 28 января 2010

кажется, что вы пытаетесь создать много разных вариантов использования, но все встроено в один супер сервис. Было бы лучше разорвать это.

http://server/product_info/123123 or http://server/product_info?product=123123
http://server/product_inventory?store=123&shelf=345

тогда вы также можете поддержать:

http://server/product_inventory?store=123

тогда PUT и DELETE имеют смысл для изменения инвентаря или добавления нового продукта.

...