2014-01-11 4 views
4

Я разрабатываю услугу REST, и я стараюсь придерживаться конвенций и рекомендаций доктора Роя Филдинга.REST Resource path design

Я представляю свою службу как конечную точку, которая предоставляет набор ресурсов. Ресурс идентифицируется с помощью URI, и клиенты api могут манипулировать ресурсами с использованием семантики HTTP (то есть различные глаголы HTTP сопоставляются с соответствующими операциями над URI).

Руководящие принципы указывают, что эти URI должны быть определены иерархическим способом, отражающим иерархию объектов. Это полезно для создания ресурсов, потому что на бэкэнд нам нужны данные для выполнения операции создания. Однако при дальнейших манипуляциях большая часть информации, включенной в URI, даже не будет использоваться службой, потому что, как правило, одного только идентификатора ресурса достаточно, чтобы однозначно идентифицировать цель операции.

Пример: рассмотрим Api, который раскрывает создание и управление продуктами. Учтите также, что продукт связан с брендом. О создании это имеет смысл, что следующее действие выполняется: HTTP POST/марка/{Brand_ID}/Продукт [Тело, содержащее вход, необходимое для создания продукта]

Создание возвращает HTTP 201, созданный с заголовок местоположения, который раскрывает местоположение вновь созданного продукта.

О дальнейших манипуляций, клиенты могут получить доступ к устройству, выполнив: HTTP PUT/марка/{Brand_ID}/продукта/{product_id} HTTP DELETE/марка/{Brand_ID}/Product/{PRODUCT_ID} и т.д.

Однако, поскольку идентификатор продукта является универсальным в области продукта, следующие манипуляции могут выполняться следующим образом: /Product/{product_id} Я придерживаюсь префикса/Марка/{brand_id} по причинам согласованности. Фактически, идентификатор бренда игнорируется службой. Вы считаете, что это хорошая практика, и разумно для поддержания четкого, однозначного определения ServiceInterface? Каковы преимущества этого, и так ли это вообще?

Также будут оценены любые указатели на лучшие практики определения URI.

Заранее спасибо

ответ

8

Вы говорите:

Руководство утверждают, что эти идентификаторы URI должны быть определены в иерархическом образом, что отражает иерархию объектов.

Хотя это часто делается таким образом, это не имеет особого отношения к дизайну API RESTful. Рой Филдинг имеет nice article, обращаясь к общим заблуждениям о REST. Там он даже говорит:

REST API не должен определять фиксированные имена ресурсов или иерархии (очевидное соединение клиента и сервера).

и

Отдыхают API должны быть введены без предварительного знания за пределами исходного URI ...

Так что не закодировать информацию в URL, который должен быть передан внутри ресурса , API RESTful должен работать, даже если вы замените все свои URL-адреса искусственными и нечувствительными URI. (Мне нравятся понятные URI как никто, но как умственное упражнение, чтобы проверить вашу «RESTfullness», это неплохо.)

Проблема моделирования URI для иерархии объекта заключается в том, что иерархия не очень часто очевидна как это выглядит. (Какова иерархия объектов между учителем, курсом и учеником?).Часто объекты находятся в сети отношений и явно не под другим объектом. Продукт может принадлежать бренду, но у вас может быть несколько поставщиков (охватывающих подмножество продуктов для нескольких брендов). И REST замечателен, чтобы выразить сложные сети отношений. Весь интернет/веб работает таким образом.

Вместо кодирования отношения в иерархии просто определяют гиперссылку в вашем ресурсе, указывающую на связанные объекты.

Для вашего конкретного примера я бы использовал POST/product/для создания нового продукта и ссылки на ваш/brand/xzy в представлении ресурса при создании продукта.

Если вы хотите узнать, какие продукты определены для определенного бренда, просто включите список ссылок в возвращаемое представление для GET/brand/xzy. Если вы хотите иметь явный ресурс, представляющий эти отношения, вы все равно можете определить GET/brand/{id}/products как URL (или/brandproducts/xzy или/34143453453) и вернуть его в качестве ссылки в ресурсе вашего бренда.

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

1

Я думаю, что это ключевой комментарий:

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

Слово ассоциируется говорит мне, что вам нужно ссылку ресурсы вместе. Итак, предположим, что существует связь между брендами и продуктами. Каждый ресурс имел бы свой набор методов (GET, PUT и т. Д.), Как вы описали, но представления должны иметь ссылки другим ресурсам, описывающим их ассоциации. Где ссылки зависят от типа ассоциации (один к одному, один-ко-многим, много-к-одному, многие-ко-многим) и направления.

Например, предположим, что существует канонический запрос этого продукта api.example.com:

GET /product/12345 

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

HTTP/1.1 200 OK 
Content-Type: application/xml; charset=utf-8 
Content-Length: ... 

<?xml version="1.0"?> 
<Product href="http://api.example.com/product/12345" rel="self" type="application/xml"/> 
    <Name>Macaroni and Cheese</Name> 
    <Brand href="http://api.example.com/brand/7329" type="application/xml"/> 
    <Manufacturer href="http://api.example.com/manufacturer/kraft" rel="parent" type="application/xml"/> 
</Product> 

Как вы можете видеть, я встраивание ссылки в представлении продукта 12345, описывающего каждое отношение. Всякий раз, когда это возможно, я стараюсь следовать HATEOAS ограничения столько, сколько я могу:

  • Существует явные связывающий текущий ресурс и связанные с ними ресурсами.
  • Необязательное описание отношения («rel»). «self» и «parent» - это описания отношения текущего ресурса и ресурса, ссылки ссылки.
  • Необязательный предпочтительный тип MIME, который необходимо запросить. Это описывает тип документа, который клиент должен ожидать, если будет выполнен запрос на последующий запрос.
  • Непрозрачные URL-адреса вместо необработанных идентификаторов. Клиенты могут просто «перемещаться» по URL-адресу, не создавая их, используя какое-либо соглашение. Обратите внимание, что URL-адреса не обязательно должны содержать уникальный идентификатор базы данных или ключ (например, «/ brands/kraft»).

Чтобы расширить некоторые предварительные концепции, предположим, что продукты имеют другие отношения. Возможно, продукты имеют иерархические отношения или продукты, заменяющие другие продукты. Все эти сложные отношения могут быть представлены ссылками. Таким образом, продвинутая представление 12345 продукта:

HTTP/1.1 200 OK 
Content-Type: application/xml; charset=utf-8 
Content-Length: ... 

<?xml version="1.0"?> 
<Product href="http://api.example.com/product/12345" rel="self" type="application/xml"/> 
    <Name>Macaroni and Cheese</Name> 
    <Brand href="http://api.example.com/brand/7329" rel="parent" type="application/xml"/> 
    <Manufacturer href="http://api.example.com/manufacturer/kraft" type="application/xml"/> 
    <!-- Other product data --> 
    <Related> 
    <Product href="http://api.example.com/product/29180" rel="prev" type="application/xml"/> 
    <Product href="http://api.example.com/product/39201" rel="next" type="application/xml"/> 
    </Related>  
</Product> 

В этом примере я использую «пред» и «рядом», чтобы представить цепочку продуктов. «Прев» можно интерпретировать как «замененный» и «следующий», который интерпретируется как «замененный». Вы можете использовать «замененные» и «вытесненные» как значения rel, но обычно используются «prev» и «next». Это действительно зависит от вас.

+0

Кажется, что ваше предложение таково: сохраните свой путь ресурса простым и включите ссылки в каждом из членов ресурса. Вы имеете дело только с случаем Get. Как бы вы создали новый продукт? I.e., кто бы вы указали на момент создания, какой производитель связан с новым продуктом? Включить его в тело запроса? Это звучит не так. Похоже, что эта информация должна быть включена в URI ресурса. –

+0

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