RESTful, гипертекстовая система должна позволять клиентам создавать новый ресурс, который зависит от трех или более ресурсов разных типов. Какой лучший способ раскрыть эту возможность?
В качестве примера, скажем, я управляю интернет-магазином. Сервер знает о четырех ресурсах:
- Заказ: группа товаров для отправки. [имеет одну пересылку]
- Назначение: место доставки. [имеет много отгрузок]
- Отгрузка: Акт отправки Продукта Клиенту. [принадлежит пункту назначения, заказу и упаковщику]
- Упаковщик: сотрудник, физически готовящий Заказ на отгрузку. [имеет много отгрузок]
Когда заказ отправлен, клиент должен записать это событие, создав новую отправку на сервере. Отгрузка потребует ссылки на пункт назначения, заказ и упаковщик.
Чтобы реализовать создание новых отправлений, я могу придумать три подхода, и мне не нравится ни один из них:
- POST к / отгрузкам с использованием типа носителя. Тип носителя «Отправка» имеет три поля: «order_uri»; "Packer_uri"; и "destination_uri". Каждый URI используется в качестве уникального идентификатора для Заказа, Упаковщика и Назначения, участвующих в Отгрузке, соответственно.
- POST в / orders / {order_id} / packers / {packer_id} / destination / {destination_id} / отгрузки с использованием типа носителя "Отправка".
- Добавить новый ресурс в систему под названием «ShipmentBuilder». POST для / shipment_builders с использованием «packer_uri», «destination_uri» и «order_uri», содержащихся в типе носителя ShipmentBuilder.
Мне не нравится Вариант 1, потому что тип носителя «Отправка» дополнительно определяет ссылки на Заказ, Упаковщик и Место назначения. Здесь «ссылка» - это хэш JSON, состоящий из читаемого человеком имени, URI и типа носителя. Добавление «order_uri», «packer_uri» и «destination_uri» к типу носителя выглядит не очень сухо, поскольку дублирует URI для связанных ресурсов.
Вариант 2 использует глубоко вложенные URI, которые не выглядят очень удобными для обслуживания и не содержат никакой значимой иерархической информации.
Вариант 3 помещает еще один уровень абстракции между клиентами и созданием отправлений, что усложняет изучение системы.
Если бы отгрузка зависела только от одного другого ресурса, вариант 2 имел бы гораздо больше смысла, но в этом случае это не так. В настоящее время я предпочитаю вариант 3, но предпочел бы что-то лучшее.
В этом примере, какова будет лучшая комбинация URI и типа носителя для создания нового Отправления? Какие еще подходы следует рассмотреть?
Обновление: ниже приведено примерное представление ресурса отгрузки в формате JSON, показывающее ссылки на заказ, упаковщик и пункт назначения. Дублирование URI, необходимое для варианта 1, появляется в хеше «отгрузки»:
{
"shipment":{
"created_at": "Wed Sep 09 18:38:31 -0700 2009",
"order_uri":"http://example.com/orders/815",
"packer_uri":"http://example.com/packers/42",
"destination_uri":"http://example.com/destinations/666"
},
"order":{
"name":"the order to which this shipment belongs",
"uri":"http://example.com/orders/815",
"media_type":"application/vnd.com.example.store.Order+json"
},
"packer":{
"name":"the person who packed this shipment",
"uri":"http://example.com/packers/42",
"media_type":"application/vnd.com.example.store.Packer+json"
},
"destination":{
"name":"the destination of this shipment",
"uri":"http://example.com/destinations/666",
"media_type":"application/vnd.com.example.store.Destination+json"
}
}
Содержимое хеша "shipment" (без поля "selected_at") будет отправлено POST. При использовании GET будет отправлено полное представление Отправления, приведенное выше.