Как должна выглядеть схема URL REST для иерархии деревьев?
Предположим, что у меня есть магазины, полки в магазине и продукты на полке. Поэтому, чтобы получить список продуктов на полке в магазине, я бы воспользовался следующим запросом:
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, просьба привести примеры того, как я могу сделать это лучше. Там слишком много людей, которые любят говорить "ОТДЫХ - это не CRUD" и "REST не RPC", а затем не дают абсолютно никаких пояснений или примеров хорошего дизайна RESTful.
Ответы
Ответ 1
Не создавайте REST api на основе структуры URL. Здесь, как я думаю, вам стоит подумать о разработке REST api.
Попытка определить интерфейс REST без обсуждения того, какие ссылки будут содержаться в том, какие ресурсы похожи на обсуждение интерфейса RPC и игнорирование параметров и возвращаемых значений.
Ответ 2
Я отметил два подхода к дизайну URI RESTful: иерархический и отфильтрованный
Я чувствую, что иерархичность слишком многословна, имеет потенциал для избыточных конечных точек (не DRY) и маскируется в том, какое состояние ресурса вам действительно интересно (в конце концов, передача 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
В конечном счете, это tomayto, tomahto
REST не требует одного над другим. Однако, по моему собственному опыту, более эффективно использовать RESTful API, который отображает отдельные объекты в одиночные конечные точки (например, сопоставления объектов RestKit на iOS) вместо того, чтобы иметь карту сущности для множества разных конечных точек на основе того, какие параметры переданы.
О REST
Что касается REST, это не протокол и не имеет RFC. Он тесно связан с HTTP/1.1 RFC как способ реализации своих CRUD-действий, но многие разработчики программного обеспечения полагают, что REST не зависит от HTTP. Я не согласен и считаю такой гипотезой, потому что оригинальная диссертация UCI Roy Fielding (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. Как всегда, ваши конкретные цели и потребности будут влиять на ваш выбор, но простота всегда является хорошей мишенью для достижения цели.
Ответ 3
Создание продукта должно быть просто POST для
http://server/product
Обновление продукта должно быть PUT до
http://server/product/$id
Получение продукта должно быть просто GET для
http://server/product/$id
Удаление продукта должно быть просто DELETE для
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-глаголы, чтобы выставить их во вселенную.
Ответ 4
Так как продукты могут быть в нескольких магазинах или на нескольких полках (категории?), у меня будет каждый номер уникального номера, независимо от его положения в иерархии. Затем используйте плоский номер продукта. Это делает API более стабильным, когда некоторые продукты, например, перемещаются в вашем магазине.
Короче говоря, не добавляйте ненужную избыточность в ваш API. Для получения списка полки достаточно идентификатора магазина, для списка продуктов достаточно идентификатора полки... и т.д.
Ответ 5
похоже, что вы пытаетесь построить много разных вариантов использования, но все становится встроенным в один суперсервер. Было бы лучше разобраться.
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 имеют смысл для изменения инвентаря или добавления нового продукта.