REST - компроміси між узгодженням вмісту через заголовок Accept та розширення


40

Я працюю над розробкою API RESTful. Ми знаємо, що хочемо повернути JSON і XML для будь-якого ресурсу. Я думав, що ми зробимо щось подібне:

GET /api/something?param1=value1
Accept:  application/xml (or application/json)

Однак хтось кинув, використовуючи розширення для цього, наприклад:

GET /api/something.xml?parm1=value1 (or /api/something.json?param1=value1)

Які компроміси з цими підходами? Краще покластися на заголовок прийняття, коли розширення не вказано, але почесні розширення, коли вказано? Чи є недолік такого підходу?


Який веб-сервер ви використовуєте? і як він аналізує URL-адреси?
Діпан Мехта

1
Я не маю уявлення про технічну (серверну) сторону речей. Попри це, я віддаю перевагу вашому підходу, тому що він використовує стандарт http, який полегшує розуміння (наприклад, коли хтось інший повинен зробити якесь технічне обслуговування на ньому за кілька років вниз). Ви можете розраховувати на розширення, коли акцепт не вказаний або має несподіване значення, але я завжди завжди йду стандартним шляхом.
Треб

@Dipan Я зламаю це з веб-API MVC4 (все ще в бета-версії). Він використовує маршрутизаційні абстракції ASP.NET, які є досить приємними.
Брендон Лінтон

1
@Treb Так, я набагато більше прихильник використання значення заголовка accept. Мені цікаво, чи є якийсь недолік для підтримки обох.
Брендон Лінтон

Відповіді:


38

Це, "Однак, по-філософськи - перший підхід є єдиним підходом", і це "Правильним офіційним підходом RESTful є використання заголовка Accept:". які широко сприймаються як справа, але і абсолютно невірно .

Ось короткий фрагмент від Роя Філдінга (який визначив REST) ​​...

"Розділ 6.2.1 не говорить про те, що переговори щодо вмісту повинні використовуватися постійно." цитувати

Ця конкретна розмова знаходиться в контексті заголовка "Accept-Language:", але те саме стосується і заголовка "Accept:", як було зрозуміло пізніше у його відповіді ...

"Я поняття не маю, чому люди не можуть бачити друге та третє посилання на верхній сторінці

http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm

які вказують на два видання PDF ".

Що він має на увазі, що немає використання різних кінцевих точок для різних представлень одних і тих же вихідних даних. (У цьому випадку одна .html кінцева точка та дві різні .pdf кінцеві точки.)

Також у подібній дискусії цього разу щодо достоїнств використання параметрів запиту порівняно з використанням розширень файлів для різних типів носіїв ...

"Тому я завжди віддаю перевагу розширенням. Жоден вибір не має нічого спільного з REST". цитувати

Знову ж таки, це дещо відрізняється від розширення Accept vs. Filename, але позиція Fielding все ще зрозуміла.

Відповідь - це насправді не має великого значення. Компроміси між двома не дуже значні, і обидва є прийнятними стилями.


3
Чудова врівноважена відповідь. Я думаю, я б додав, що іноді це "очевидно" з URI, що певний вміст призначений. наприклад, .html розширення або .pdf розширення в URI. І в цьому випадку насправді не потрібно підтримувати переговори щодо контенту, а відсутність вмісту, який міститься в URI, полегшує людину спільний доступ до URI і використання його для посилання на речі таким чином, щоб вони могли негайно споживати. В інших випадках, наприклад, якщо ви хочете уникнути розширень у своїх URI, та / або ви хочете відкрити веб-API, який однаково підтримує декілька типів вмісту json / XML, заголовок прийняття може краще відповідати.
Тім Ловелл-Сміт

Оновлена ​​відповідь, щоб містити нові посилання. Я думаю, що групи Yahoo змінили свою структуру.
Філ Стерджон

Я не погоджуюсь. Мова опису ресурсів, що повертається сервером, не повинен відповідати бізнес-логіці, що виконується кінцевою точкою обслуговування. Наявність декількох URI для однієї і тієї ж кінцевої точки обслуговування, просто для розміщення різних мов опису ресурсів, здається нерозумінням того, як повинні бути побудовані REST URI.
Dejay Clayton

10

Правильний офіційний підхід RESTful - використовувати Accept:заголовок.

Однак ви повинні бути обережними, щоб не порушити кешируемость, що є однією з вимог REST. Потрібно мати Vary: Acceptзаголовок і кеш, які це розуміють. В ідеальному світі ви б його мали, але в реальному житті ваша мілана може відрізнятися. Тож друге рішення не настільки чисте, але може бути більш практичним.

Також зауважте, що деякі дуже старі браузери ігнорували заголовки, покладаючись на розширення.


1
Фактично неточні. Дивіться прийняту відповідь.
Філ Стерджонж

9

Технічно це не має особливого значення - ваш веб-сервер зможе пройти процес належним чином, як це виглядає. (Я припускаю, що це не схоже на шоустоппер).

Однак по-філософськи - перший підхід - єдиний підхід. У REST URL-адреса насправді вказує лише на URI - це лише ресурс. Подумайте на мить цей ресурс так само, як об’єкт в об'єктно-орієнтованому програмуванні. Ви спілкуєтесь з цим ресурсом лише за допомогою чотирьох методів (він же GET / POST / PUT / DELETE-або, якщо все, що дозволяє транспорт), але цей метод не стає описом об'єкта. Таким же чином, аспекти повернення значення не є URI. Об'єкт все-таки є щось, а не щось.xml або something.json

Припустимо, якщо ви не хочете використовувати заголовок Accept, але якщо ви все ще хочете бути по-справжньому філософськими, я не маю на увазі щось таке:

GET /api/something?parm1=value1&return_type=xml

на відміну від

GET /api/something.xml?parm1=value1 (or /api/something.json?param1=value1)

Але, як я сказав, ця різниця є лише філософською.


+1 Діпане, ви праві, окрім одного: / api / щось? Return_type = xml все ще не в спокої . Причина, по якій це не RESTful, полягає в тому, що URL-адреси непрозорі. IOW, з точки зору протоколу, немає різниці між / api / щось / xml та / api / щось? Xml. Див. W3.org/DesignIssues/Axioms.html .
Марк Е. Хааз

0

@vartec: Я думаю, ви помиляєтесь

Належний офіційний принцип RESTful говорить, що нічого не повинно бути прихованим у заголовках HTTP, оскільки саме URI відкривається або посилається, будь-яка деталь про запит / відповідь повинна надаватися як частина URI

Тому я настійно рекомендую уникати використання заголовка для деталей, які стосуються запиту та відповіді, і дотримуватися цього

 GET /api/something.xml?parm1=value1 (or /api/something.json?param1=value1)

Я не в змозі швидко знайти посилання, але я опублікую їх з ними (насправді ви можете посилатися на книгу публікацій O'reilly "RESTful web services" ( http://shop.oreilly.com/product/9780596529260.do ) що підтверджує те саме


17
-1 Зовсім неправильно. З одного боку, URL - адреса буде відправлений у заголовках HTTP. Крім того, кожна окрема URL-адреса повинна представляти окремий ресурс. Кодування XML і JSON одного і того ж вмісту очевидно не є двома різними ресурсами; вони є двома різними уявленнями одного ресурсу.
Марк Е. Хааз

HTTP заголовки є законним і рекомендованим місцем для зберігання "метаданих обміну повідомленнями", таких як: облікові дані безпеки, ідентифікатор кореляції, ідентифікатор сеансу, транзакційний контекст, формати даних. Така інформація не повинна захаращувати ваші URL-адреси чи корисну навантаження вашого повідомлення.
Пауло Мерсон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.