Чи правильно повертати HTML з API JSON?


25

У своєму теперішньому проекті я відповідаю за впровадження послуги, яка передбачає споживання новостворених API RESTful, документально підтверджених як виключно підтримуючий JSON.

Клієнт послідовно робить запити із заголовком акцепту "application / json" та типом вмісту "application / json". Однак деякі кінцеві точки надсилають відповідь із типом HTML-вмісту, навіть тілом HTML. Для мене це явно неправильний підхід і ніколи не може бути виправданим.

Протягом проекту ця сама практика застосовувалася у двох різних постачальників та двох різних служб. Мені довелося виправдовувати, чому послуги потрібно змінити. Постачальники заявили, що клієнт повинен впоратися з цим, і навіть моя бібліотека REST на вибір була поставлена ​​під сумнів (RestEasy), тому що він не справляється з цим за замовчуванням "з коробки".

Це було головним моментом розчарування. Я не можу знайти багато посилань, щоб підкріпити свій аргумент, я припускаю, що це тому, що справа суперечлива, оскільки це так очевидно.

Питання в тому, я щось пропускаю? я педантично ставлюсь до цього? Чи нормально мати JSON API, який не містить типу вмісту програми / json у цьому сценарії? Посилання будуть вдячні. Як ви вирішуєте цю ситуацію з комерційної точки зору?


1
Під контекстним типом ви маєте на увазі заголовка HTTP типу вмісту?
Мар'ян Венема

Так, я переглядаю заголовок типу вмісту HTTP. Відредаговано.
phillip.darley

Ну, принаймні, вони не повинні називати це "API JSON REST", коли це HTML REST API.
Бергі

Відповіді:


28

Коли ви надсилаєте acceptзаголовок із запитом певного типу медіа, сервер не повинен надсилати ще щось, і, звичайно, не з кодом статусу 200 ОК

Від Restpatterns.org :

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

(Наголос мій)

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

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


1
+1. Я погоджуюся з цією відповіддю, але, на жаль, це слово shouldвживається неодноразово в специфікаціях HTTP. Ми повинні почати онлайн-петицію, щоб змінити ці слова must.
Реакційний

3
@MarjanVenema "повинен" є правильним, оскільки в розділі 10 від того ж rfc є зауваження: "HTTP / 1.1 серверам дозволяється повертати відповіді, неприйнятні відповідно до заголовків прийняття, надісланих у запиті. У деяких випадках це може навіть бажано надсилати відповідь 406 ".
imela96

1
Якщо клієнт запитує ресурс, який насправді не має представлення JSON, то, як би вони не бажали JSON, їм, можливо, краще отримати щось інше, що є остаточним; Ви не гарантовано отримаєте 406. Важливо те, що сервер повинен описати, яким саме є тип вмісту відповіді.
Стипендіати Доналу

6
@DonalFellows: Ні, їм було б краще бути поінформованими про те, що є насправді. Сервер повинен не просто надсилати нічого назад, що вважає за потрібне, але надсилати відповідь 406 Неприйнятна, як зазначено в стандарті. Майте на увазі, що коли клієнт спеціально запитує тип медіа та не вказує жодних резервних копій, він, ймовірно, не може обробити будь-який інший тип медіа.
Мар'ян Венема

2
@ imela96: той факт, що Інтернет ніколи не був суворим, саме те, що призвело до труднощів у спробі підтримки різних браузерів та серверів, які тепер змушені залишатися назад сумісними з недійсними html, оскільки там просто занадто багато цього (і це, на жаль, все ще створюється).
Мар'ян Венема

9

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

API RESTful (чи говориш ти зовсім не в спокої на рівні 1 або щось на рівні 3 або вище, див. Http://martinfowler.com/articles/richardsonMaturanceModel.html ) - це про те, як ти взаємодієш з API, а не про формат вмісту, надісланого або отриманого від. Йдеться навіть не про протоколи чи транспортні механізми ...

Аналогічно, API JSON - це API, який підтримує використання JSON як формату даних - він може бути, а може і не бути спокійним, він може бути, а може і не бути реалізований за допомогою HTTP і (і це ключовий момент), він може або не може підтримувати JSON виключно.

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

Потім стає цікавим питання, якщо викликається мій API, який підтримує різноманітні формати вмісту, не повідомляючи, який формат очікує клієнт, то який формат він повинен повернути ...? Це має тенденцію до релігійного аргументу, але HTML надає постачальнику можливість включати корисну інформацію (наприклад, "пам'ятайте, щоб встановити заголовок прийняття вмісту").

Щоб відповісти на запитання API, спокійний та той, що підтримує json, повинен абсолютно мати змогу повернути HTML, якщо це запитуваний контент.


1
Я беру обидва ваші моменти і відповідно відредагував своє запитання. Те, що послуга RESTful, не має значення, і я детально пояснив, що клієнт приймає "заявку / json" у кожному запиті.
phillip.darley

Я б сказав, що "RESTful JSON API" має дуже очевидне значення.
gnasher729

1
Я б сказав, що мої вчителі доклали дуже багато зусиль, щоб переконатися, що ми зрозуміли, чому «ніколи не вважай» ключовою частиною того, щоб бути хорошим програмістом
Мерф

5

Клієнт послідовно робить запити із заголовком акцепту "application / json" та типом вмісту "application / json"

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

Протягом проекту ця сама практика застосовувалася у двох різних постачальників та двох різних служб. Мені довелося виправдовувати, чому послуги потрібно змінити. Постачальники заявили, що клієнт повинен впоратися з цим, і навіть моя бібліотека REST на вибір була поставлена ​​під сумнів (RestEasy), тому що він не справляється з цим за замовчуванням "з коробки".

Ну, я маю погодитися з продавцем. Це їхня послуга, і якщо вони чітко документують особливі випадки її використання, то ви не можете дійсно нав'язувати їх зміні. Для них це недолік, оскільки розробники будуть повільно приймати API, і якби вони слухали, що потрібно розробникам, вони б це змінили, але, на жаль, немає правила, що вони повинні дотримуватися стандартів.

Питання: я щось пропускаю?

Запити заголовків нічого не означають, якщо вони не будуть перервані правильно на іншому кінці. Я знаю, що якщо я розробляю веб-API за допомогою PHP, то до біса з заголовками запитів. Я можу відповісти чим завгодно. Тоді як служба, сконфігурована в IIS з C #, пропонує набагато простіше обробляти заголовки запитів, їх тип та обробляти тип відповіді. Це має багато спільного з інструментами, які постачальник використовував для створення API.

Я з цього приводу будучи педантичним?

Так і ні. У мене є друзі розробника, які не зможуть пройти повз це. Вони стають настільки виправленими проблемою і не зможуть приступити до виконання інших завдань, поки API не працює так, як вони очікують, що він працює. Тепер це педантично.

Це проблема, оскільки постачальник створив "більше роботи" для виконання ваших завдань. Хтось би це засмутив. Я знаю, що був би.

Чи нормально мати JSON API, який не містить типу вмісту програми / json у цьому сценарії?

Абсолютно, але це не є хорошою практикою.

Клієнт може лише повідомити серверу, що таке тип контексту request. Він не має можливості застосовувати тип вмісту для response. Клієнт може лише повідомити сервер, що він буде acceptзібрати можливі типи вмісту.

Визначення поля заголовка

Поле Прийняття заголовка запиту може використовуватися для визначення певних типів носія, прийнятних для відповіді. Заголовки акцепту можуть бути використані для вказівки, що запит спеціально обмежений невеликим набором бажаних типів, як у випадку запиту на рядкове зображення.

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

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

Посилання будуть вдячні. Як ви вирішуєте цю ситуацію з комерційної точки зору?

Я зіткнувся з цією проблемою в кількох проектах. Ви postпередаєте дані JSON на сервер, і він повертає або відповідь JSON, або HTML.

Дізнатися, який тип відповіді був насправді, не так вже й багато. Якщо перший символ є {або [ви можете припустити JSON. Якщо це, <ви можете припустити HTML. Ось як я впорався з цим у минулому. Іноді програміст, який написав API, знає джек про заголовки HTTP. Все повертається як text/htmlвідповіді. Якщо вам пощастило, у них Apache налаштований за замовчуванням, до text/plainякого іноді може допомогти.

Ці проблеми існують і будуть існувати далеко в майбутньому. Зв'язок між сервером та сервером - це далеко не регульована діяльність. Немає керівного органу, який би вигнав постачальника з профспілки на сервер, який дає погані відповіді HTTP.


Це відповідає відповіді @Marjan Venema, але ще одним ключовим моментом, який ви піднімаєте, є документація такої поведінки. Щоб додати моє розчарування, продавець не підтвердив цю поведінку. Тип вмісту змінюється залежно від стану сеансу, але документально підтверджено лише відповідь JSON.
phillip.darley
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.