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

40

Я работаю над созданием RESTful API. Мы знаем, что хотим вернуть 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)

Каковы компромиссы с этими подходами? Лучше ли полагаться на заголовок accept, когда расширение не указано, но соблюдать расширения, когда оно указано? Есть ли недостаток этого подхода?

Брэндон Линтон
источник
Какой веб-сервер вы используете? и как он разбирает URL?
Дипан Мехта
1
Я понятия не имею о технической (серверной) стороне вещей. При этом я предпочитаю ваш подход, потому что он использует стандарт http, что облегчает его понимание (например, когда кто-то другой должен выполнить его техническое обслуживание через несколько лет в будущем). Вы могли бы положиться на расширение, когда accept не указан, или имеет неожиданное значение, но я всегда сначала пошел бы по стандартному пути.
Треб
@Dipan Я взломал это с помощью веб-API MVC4 (все еще в бета-версии). Он использует абстракции маршрутизации ASP.NET, которые довольно хороши.
Брэндон Линтон
1
@Treb Да, я гораздо больше люблю использовать значение заголовка accept. Мне интересно, есть ли какой-либо недостаток для поддержки обоих.
Брэндон Линтон

Ответы:

38

Это, «Однако, философски - первый подход - единственный подход», и это «Правильный официальный подход RESTful - использовать Accept: header». которые широко воспринимаются как дело, но и абсолютно неверно .

Вот краткий фрагмент Роя Филдинга (который определил REST) ​​...

«в разделе 6.2.1 не сказано, что согласование контента должно использоваться постоянно». цитировать

Этот конкретный разговор находится в контексте заголовка «Accept-Language:», но то же самое относится в равной степени к заголовку «Accept:», как было ясно позже в его ответе ...

«Я понятия не имею, почему люди не видят вторую и третью ссылку на верхней странице

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

это указывает на два издания PDF. "

Он имеет в виду, что нет проблем в использовании разных конечных точек для разных представлений одних и тех же исходных данных. (В этом случае одна конечная точка .html и две разные конечные точки .pdf.)

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

«Вот почему я всегда предпочитаю расширения. Ни один из вариантов не имеет ничего общего с REST». цитировать

Опять же, это немного отличается от Accept против расширений имени файла, но позиция Филдинга все еще ясна.

Ответ - это действительно не имеет большого значения. Компромиссы между этими двумя не очень существенны, и оба - приемлемые стили.

Том Кристи
источник
3
Отличный сбалансированный ответ. Я думаю, что я бы добавил, что из URI «очевидно», что определенное содержание предназначено. например, расширение .html или расширение .pdf в URI. И в этом случае на самом деле нет необходимости поддерживать согласование контента, а наличие контента, неявного в URI, облегчает людям возможность делиться URI и использовать его для связи с вещами так, как они могут немедленно потреблять. В других случаях, например, если вы хотите избежать расширений в ваших URI и / или хотите предоставить веб-API, который в равной степени поддерживает несколько типов контента json / XML, заголовок accept может подойти лучше.
Тим Ловелл-Смит
Обновленный ответ содержит новые ссылки. Я думаю, что Yahoo группы изменили свою структуру вокруг.
Фил Осетрина
Я не согласен. Язык описания ресурсов, возвращаемый сервером, не должен относиться к бизнес-логике, выполняемой конечной точкой службы. Наличие нескольких URI для одной и той же конечной точки службы, просто для размещения разных языков описания ресурсов, кажется неправильным пониманием того, как должны создаваться REST URI.
Деджей Клэйтон
10

Надлежащим официальным подходом RESTful является использование Accept:заголовка.

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

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

Vartec
источник
1
Фактически неточно. Смотрите принятый ответ.
Фил Осетрина
9

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

Однако философски - первый подход - единственный подход. В REST URL фактически указывает только на URI, который является только ресурсом. Задумайтесь на мгновение этот ресурс такой же , как объект в объектно - ориентированном программировании. Вы общаетесь с этим ресурсом только через 4 метода (иначе говоря, GET / POST / PUT / DELETE -или, если это позволяет транспорт), но этот метод не становится описанием объекта. Точно так же аспекты возвращаемого значения не являются URI. Объект все еще что-то, а не что- то. Xml или что-то.

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

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-адресов. Итак, с точки зрения протокола, нет разницы между / 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 ) что подтверждает то же самое

Basav
источник
17
-1 Совершенно неправильно. С одной стороны, URL - адрес будет отправлен в заголовках HTTP. Кроме того, каждый отдельный URL должен представлять отдельный ресурс. Кодировки XML и JSON одного и того же контента явно не являются двумя разными ресурсами; это 2 разных представления одного и того же ресурса.
Марк Э. Хаас
Заголовки HTTP являются законным и рекомендуемым местом для хранения «метаданных обмена сообщениями», таких как: учетные данные безопасности, идентификатор корреляции, идентификатор сеанса, контекст транзакции, форматы данных. Такая информация не должна загромождать ваши URL-адреса или полезную нагрузку вашего сообщения.
Пауло Мерсон