Можно ли вернуть HTML из API JSON?

25

В моем текущем проекте я отвечаю за реализацию службы, которая включает использование только что созданных API RESTful, документированных как исключительно поддерживающие JSON.

Клиент последовательно делает запросы с заголовком accept 'application / json' и типом контента 'application / json'. Однако некоторые конечные точки отправляют ответ с типом содержимого HTML, даже с текстом HTML. Для меня это явно неправильный подход и никогда не может быть оправданным.

На протяжении всего проекта эта же практика применялась для двух разных поставщиков и двух разных сервисов. Я обнаружил, что должен объяснить, почему услуги должны быть изменены. Поставщики заявили, что клиент должен справиться с этим, и даже моя библиотека REST была опрошена (RestEasy), потому что она не справляется с этим по умолчанию «из коробки».

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

Вопрос в том, что я что-то упустил? я педантичен об этом? Можно ли в этом сценарии иметь JSON API, у которого нет типа содержимого application / json? Ссылки будут оценены. Как вы решаете эту ситуацию с коммерческой точки зрения?

phillip.darley
источник
1
Под типом контекста подразумевается HTTP-заголовок типа контента?
Марьян Венема
Да, я ссылаюсь на заголовок типа содержимого HTTP. Ред.
phillip.darley
Ну, по крайней мере, они не должны называть его «JSON REST API», когда это HTML REST API.
Берги

Ответы:

28

Когда вы отправляете acceptзаголовок, запрашивающий определенный тип носителя, сервер не должен отправлять обратно что-то еще, и, скорее всего, не с кодом состояния 200 OK

От Restpatterns.org :

Если поле заголовка Accept отсутствует, предполагается, что клиент принимает все типы мультимедиа. Если присутствует поле заголовка Accept, и если сервер не может отправить ответ, который является приемлемым согласно комбинированному значению поля Accept, то сервер ДОЛЖЕН отправить 406 (не приемлемый) ответ.

(Акцент мой)

Restpatterns.org берет это из фактического стандарта HTTP: определения полей заголовка - Принять

Короче говоря: вы не педантичны. Службы не следуют стандарту HTTP, если они возвращают HTML, когда заголовок accept определенно указывает им возвращаться application/jsonи ничего больше.

Марьян Венема
источник
1
+1. Я согласен с этим ответом, но, к сожалению, слово shouldчасто используется в спецификациях HTTP. Мы должны начать онлайн-петицию, чтобы эти слова были изменены must.
Reactgular
3
@MarjanVenema «следует» правильно, потому что в разделе 10 из того же rfc есть примечание: «HTTP / 1.1 серверам разрешено возвращать ответы, которые не являются приемлемыми в соответствии с заголовками принятия, отправленными в запросе. В некоторых случаях это может даже предпочтительнее отправки 406 ответа. "
imel96
1
Если клиент запрашивает ресурс, который действительно не имеет представления JSON, то независимо от того, насколько сильно он хочет JSON, ему, возможно, лучше получить что-то еще, что является окончательным; вы не гарантированно получите 406. Важно, чтобы сервер описывал тип содержимого ответа.
Donal Fellows
6
@DonalFellows: Нет, им было бы лучше узнать, что на самом деле происходит. Сервер должен не просто отправлять назад что-либо, что он считает подходящим, но и отправлять 406 неприемлемый ответ, как указано в стандарте. Имейте в виду, что когда клиент специально запрашивает тип мультимедиа и не указывает никаких запасных вариантов, он, вероятно, не может обработать какой-либо другой тип мультимедиа.
Марьян Венема
2
@ imel96: тот факт, что интернет никогда не был строгим, привел к трудностям в поддержке различных браузеров и к тому, что теперь серверы вынуждены поддерживать обратную совместимость с недействительными html, поскольку их слишком много (и это, к сожалению, все еще создается).
Марьян Венема
9

Что вы подразумеваете под «RESTful JSON API» - я думаю, что первая проблема здесь заключается в том, что вы путаете понятия (или, возможно, кто-то между вами и вашими техническими коллегами у ваших «поставщиков»).

API RESTful (независимо от того, говорите ли вы на самом деле на уровне 1 или что-то на уровне 3 или выше, см. Http://martinfowler.com/articles/richardsonMaturityModel.html ) - это способ взаимодействия с API, а не формат содержимого, отправленного или полученного от. Это даже не о протоколах или транспортных механизмах ...

Точно так же JSON API - это API, который поддерживает использование JSON в качестве формата данных - он может быть или не быть спокойным, он может быть или не быть реализован с использованием HTTP и (и это ключевой момент) он может поддерживать или не поддерживать JSON исключительно.

Хороший API работает над HTTP (ее разумно предположить , что в контексте вы говорите о АНИ открытого над HTTP) должны позволять вам содержание запроса в различных форматах , и эти форматы могут (и , возможно , должны) включать в HTML, а также JSON и XML. Зачем? Ну, это сделало бы изучение API намного проще, концептуально это обеспечивает мгновенный UX на основе браузера для любых целей и так далее ...

Тогда возникает интересный вопрос: вызывается ли мой API, поддерживающий различные форматы контента, без указания того, какой формат ожидает клиент, а затем какой формат он должен вернуть ...? Это имеет тенденцию к религиозному аргументу - но HTML дает провайдеру возможность включать полезную информацию (например, «не забудьте установить заголовок принятия контента»).

Чтобы ответить на вопрос API, тот, который успокаивает, и тот, который поддерживает json, должен быть абсолютно в состоянии вернуть HTML, если это запрошенный контент.

Murph
источник
1
Я взял обе ваши точки и соответственно отредактировал свой вопрос. Тот факт, что служба является RESTful, не имеет значения, и я подробно описал, что клиент принимает 'application / json' в каждом запросе.
phillip.darley
Я бы сказал, что «RESTful JSON API» имеет очень очевидное значение.
gnasher729
1
Я бы сказал, что мои учителя приложили немало усилий, чтобы убедиться, что мы понимаем, почему «никогда не предполагать» - это ключевая часть хорошего программиста
Мерф
5

Клиент последовательно делает запросы с заголовком accept 'application / json' и типом контента 'application / json'

Да, это правильно, но это не означает, что поставщик заботится. Хотя я полностью понимаю ваше разочарование, потому что я также думаю, что сервис JSON всегда должен давать ответ JSON, но есть много примеров, когда это не так.

На протяжении всего проекта эта же практика применялась для двух разных поставщиков и двух разных сервисов. Я обнаружил, что должен объяснить, почему услуги должны быть изменены. Поставщики заявили, что клиент должен справиться с этим, и даже моя библиотека REST была опрошена (RestEasy), потому что она не справляется с этим по умолчанию «из коробки».

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

Вопрос в том, что я что-то упустил?

Заголовки запроса ничего не значат, если они не прерваны правильно на другом конце. Я знаю, что если я разрабатываю веб-API с использованием PHP, то к черту заголовки запросов. Я могу ответить всем, что я хочу. Принимая во внимание, что служба, настроенная в IIS с C #, предлагает гораздо более простую обработку заголовков запросов, их типа и типа ответа. Это во многом связано с инструментами, которые поставщик использовал для создания API.

Я педантичен по этому поводу?

Да и нет. У меня есть друзья-разработчики, которые не смогут пройти мимо этого. Они будут настолько зациклены на проблеме и не смогут выполнять другие задачи, пока API не будет работать так, как они ожидают. Теперь это педантично.

Это проблема, потому что поставщик создал «больше работы» для выполнения ваших задач. Любой был бы разочарован этим. Я знаю, что буду.

Можно ли в этом сценарии иметь JSON API, у которого нет типа содержимого application / json?

Абсолютно, но это не очень хорошая практика.

Клиент может только сказать серверу, каков тип контекста request. У него нет возможности применять тип контента для response. Клиент может только сообщить серверу, что это будет acceptнабор возможных типов контента.

Определения полей заголовка

Поле заголовка запроса Accept может использоваться для указания определенных типов мультимедиа, которые являются приемлемыми для ответа. Заголовки Accept могут использоваться для указания того, что запрос конкретно ограничен небольшим набором требуемых типов, как в случае запроса встроенного изображения.

Клиент может запросить изображение image/jpeg, но сервер отвечает text/htmlи кодом состояния, 404если изображение не было найдено. Серверы также могут отвечать неправильно. Есть много сайтов Wordpress, которые отвечают text/htmlи код состояния 200файлов, которые не найдены.

Теперь это все ПЛОХАЯ практика со стороны сервера. Я пытаюсь вам сказать, что это абсолютно возможно и часто случается. Люди не знают, что делают, когда настраивают эти вещи.

Ссылки будут оценены. Как вы решаете эту ситуацию с коммерческой точки зрения?

Я столкнулся с этой проблемой в нескольких проектах. Вы postотправляете данные JSON на сервер, и он возвращает ответ в формате JSON или HTML.

Это действительно не имеет большого значения, чтобы знать, какой тип был в ответе. Если первый символ {или [вы можете принять JSON. Если это <вы можете принять HTML. Вот как я справился с этим в прошлом. Иногда программист, который написал API, знает все о заголовках HTTP. Все возвращается как text/htmlответы. Если вам повезет, у них Apache настроен по умолчанию, text/plainчто иногда может помочь.

Эти проблемы существуют и будут существовать в будущем. Обмен данными между серверами - безусловно, нерегулируемая деятельность. Не существует руководящего органа, который бы исключил поставщика из объединения для сервера, который дает неверные ответы HTTP.

Reactgular
источник
Это согласуется с ответом @Marjan Venema, но другой ключевой момент, который вы затронули, - документирование этого поведения. Чтобы добавить к моему разочарованию, продавец не задокументировал это поведение. Тип содержимого варьируется в зависимости от состояния сеанса, но документируется только ответ JSON.
phillip.darley