Czy zwrócenie kodu HTML z interfejsu API JSON jest w porządku?

25

W moim obecnym projekcie jestem odpowiedzialny za wdrożenie usługi polegającej na wykorzystaniu nowo utworzonych interfejsów API RESTful, udokumentowanych wyłącznie jako wsparcie dla JSON.

Klient konsekwentnie wysyła żądania z nagłówkiem accept „application / json” i typem treści „application / json”. Jednak niektóre punkty końcowe wysyłają odpowiedź z typem treści HTML, nawet z treścią HTML. Dla mnie jest to oczywiście niewłaściwe podejście i nigdy nie może być uzasadnione.

W całym projekcie ta sama praktyka została zastosowana u dwóch różnych dostawców i dwóch różnych usług. Musiałem uzasadnić, dlaczego usługi musiały zostać zmienione. Dostawcy stwierdzili, że klient powinien sobie z tym poradzić i nawet moja wybrana biblioteka REST została zakwestionowana (RestEasy), ponieważ domyślnie nie radzi sobie z tym „od razu”.

To był główny punkt frustracji. Nie mogę znaleźć wielu odniesień do poparcia mojego argumentu, zakładam, że dzieje się tak, ponieważ kwestia ta jest dyskusyjna, ponieważ jest tak oczywista.

Pytanie brzmi: czy coś mi brakuje? czy jestem pedantyczny? Czy jest OK mieć interfejs API JSON, który nie zawiera treści typu application / json w tym scenariuszu? Referencje będą mile widziane. Jak rozwiązać tę sytuację z komercyjnego punktu widzenia?

phillip.darley
źródło
1
Pod pojęciem kontekstowym rozumiesz nagłówek HTTP typu treści?
Marjan Venema,
Tak, odnoszę się do nagłówka typu treści HTTP. Edytowane.
phillip.darley,
Cóż, przynajmniej nie mogą nazywać go „JSON REST API”, gdy jest to HTML REST API.
Bergi

Odpowiedzi:

28

Gdy wysyłasz acceptnagłówek z żądaniem określonego typu nośnika, serwer nie powinien odsyłać czegoś innego, a na pewno nie z kodem stanu 200 OK

Od Restpatterns.org :

Jeśli nie ma pola Akceptuj nagłówek, zakłada się, że klient akceptuje wszystkie typy nośników. Jeśli obecne jest pole nagłówka Akceptuj, a serwer nie może wysłać odpowiedzi, która jest akceptowalna zgodnie z połączoną wartością pola Akceptuj, wówczas serwer POWINIEN wysłać odpowiedź 406 (niedopuszczalną).

(Moje podkreślenie)

Restpatterns.org bierze to z faktycznego standardu HTTP: Definicje pól nagłówka - Akceptuj

Krótko mówiąc: nie jesteś pedantyczny. Usługi nie są zgodne ze standardem HTTP, jeśli zwracają HTML, gdy nagłówek akceptujący wyraźnie mówi im o zwrocie application/jsoni nic więcej.

Marjan Venema
źródło
1
+1. Zgadzam się z tą odpowiedzią, ale niestety słowo shouldto jest wielokrotnie używane w specyfikacjach HTTP. Musimy rozpocząć petycję online, aby zmienić te słowa na must.
Reactgular,
3
@MarjanVenema „powinien” jest poprawny, ponieważ w sekcji 10 tego samego pliku rfc znajduje się uwaga: „Serwery HTTP / 1.1 mogą zwracać odpowiedzi, które są niedopuszczalne zgodnie z nagłówkami akceptacji przesłanymi w żądaniu. W niektórych przypadkach może to nawet być lepszym rozwiązaniem niż wysłanie odpowiedzi 406 ”.
imel96
1
Jeśli klient żąda zasobu, który tak naprawdę nie ma reprezentacji JSON, to bez względu na to, jak bardzo chce JSON, być może lepiej jest otrzymać coś innego, co jest ostateczne; nie masz gwarancji, że otrzymasz 406. Co ważne, serwer powinien opisać, jaki jest typ treści odpowiedzi.
Donal Fellows,
6
@DonalFellows: Nie, lepiej byłoby, gdyby zostali poinformowani o tym, co się faktycznie dzieje. Serwer powinien nie tylko odesłać z powrotem coś, co uzna za stosowne, ale wysłać 406 niedopuszczalną odpowiedź, jak podano w standardzie. Należy pamiętać, że gdy klient konkretnie żąda typu nośnika i nie określa żadnych awarii, prawdopodobnie nie ma możliwości przetworzenia żadnego innego typu nośnika.
Marjan Venema,
2
@ imel96: fakt, że internet nigdy nie był ścisły, właśnie doprowadził do trudności w próbie obsługi różnych przeglądarek i do zmuszania serwerów do zachowania zgodności wstecznej z nieważnym HTML-em, ponieważ jest tam po prostu zbyt wiele (i niestety wciąż jest tworzony).
Marjan Venema,
9

Co rozumiesz przez „RESTful JSON API” - Myślę, że pierwszym problemem tutaj jest mieszanie koncepcji (a może ktoś między tobą a twoimi technicznymi odpowiednikami u „dostawców”).

Interfejs API RESTful (niezależnie od tego, czy mówisz, wcale nie spoczywa na poziomie 1, czy coś na poziomie 3 lub wyższym, patrz http://martinfowler.com/articles/richardsonMaturityModel.html ) dotyczy sposobu interakcji z interfejsem API, a nie format treści wysyłanej lub otrzymywanej od. Nie chodzi nawet o protokoły lub mechanizmy transportowe ...

Podobnie interfejs API JSON jest interfejsem API, który obsługuje użycie JSON jako formatu danych - może, ale nie musi być kojący, może być implementowany za pomocą protokołu HTTP i (i to jest kluczowy punkt) może obsługiwać JSON lub nie wyłącznie.

Dobre API działa przez HTTP (jej przyjąć, że w kontekście mówisz API odsłoniętej przez HTTP) powinno pozwolić na żądanie treści w różnych formatach i te formaty mogą (i ewentualnie powinien) to HTML, jak również JSON i XML. Czemu? Cóż, znacznie ułatwiłoby to naukę API, koncepcyjnie zapewnia natychmiastowy interfejs użytkownika oparty na przeglądarce do dowolnego celu i tak dalej ...

Ciekawe staje się zatem pytanie, czy mój interfejs API, który obsługuje różne formaty treści, jest wywoływany bez powiadomienia, jakiego formatu oczekuje klient, a który powinien zwrócić ... Prowadzi to do argumentów religijnych - ale HTML daje dostawcy możliwość włączenia pomocnych informacji (takich jak „pamiętaj, aby ustawić nagłówek akceptowania treści”).

Aby odpowiedzieć na pytanie, interfejs API, który jest spokojny i taki, który obsługuje json, powinien absolutnie być w stanie zwrócić HTML, jeśli jest to żądana treść.

Murph
źródło
1
Przyjmuję obie twoje uwagi i odpowiednio zredagowałem moje pytanie. Fakt, że usługa jest w trybie RESTful, nie ma znaczenia i szczegółowo opisałem, że klient akceptuje „application / json” w każdym żądaniu.
phillip.darley,
Powiedziałbym, że „RESTful JSON API” ma bardzo oczywiste znaczenie.
gnasher729
1
Powiedziałbym, że moi nauczyciele włożyli wiele wysiłku w upewnienie się, że zrozumieliśmy, dlaczego „nigdy nie zakładać” było kluczową częścią bycia dobrym programistą
Murph
5

Klient konsekwentnie wysyła żądania z nagłówkiem accept „application / json” i typem treści „application / json”

Tak, jest to właściwe postępowanie, ale nie oznacza, że ​​sprzedawca się tym przejmuje. Chociaż całkowicie rozumiem twoją frustrację, ponieważ uważam również, że usługa JSON powinna zawsze dawać odpowiedź JSON, ale istnieje wiele przykładów, w których tak nie jest.

W całym projekcie ta sama praktyka została zastosowana u dwóch różnych dostawców i dwóch różnych usług. Musiałem uzasadnić, dlaczego usługi musiały zostać zmienione. Dostawcy stwierdzili, że klient powinien sobie z tym poradzić i nawet moja wybrana biblioteka REST została zakwestionowana (RestEasy), ponieważ domyślnie nie radzi sobie z tym „od razu”.

Cóż, muszę się zgodzić ze sprzedawcą. To ich usługa i tak długo, jak wyraźnie dokumentują specjalne przypadki korzystania z niej, tak naprawdę nie można narzucić, że to zmieniają. Jest to dla nich wada, ponieważ programiści będą powoli przyjmować swój interfejs API, a jeśli posłuchają tego, czego potrzebują programiści, to zmienią go, ale niestety nie ma zasady, że muszą przestrzegać standardów.

Pytanie, czy coś mi umknęło?

Nagłówki żądań nic nie znaczą, chyba że zostaną poprawnie przerwane na drugim końcu. Wiem, że jeśli opracuję internetowy interfejs API za pomocą PHP, to do diabła z nagłówkami żądań. Mogę odpowiadać na wszystko, co chcę. Natomiast usługa skonfigurowana w IIS z C # oferuje znacznie łatwiejszą obsługę nagłówków żądań, ich typu i obsługę typu odpowiedzi. Ma to wiele wspólnego z narzędziami, których dostawca użył do zbudowania API.

Jestem pedantyczny w tej sprawie?

Tak i nie. Mam znajomych programistów, którzy nie byliby w stanie przejść dalej. Zostałyby tak naprawione przez problem i nie byłyby w stanie wykonywać innych zadań, dopóki interfejs API nie będzie działał w oczekiwany sposób. To jest pedantyczne.

Jest to problem, ponieważ dostawca stworzył „więcej pracy” w celu wykonania twoich zadań. Sfrustrowałoby to każdego. Wiem, że byłbym.

Czy jest OK mieć interfejs API JSON, który nie zawiera treści typu application / json w tym scenariuszu?

Oczywiście, ale to nie jest dobra praktyka.

Klient może tylko powiedzieć serwerowi, jaki jest typ kontekstowy request. Nie ma możliwości narzucenia typu zawartości dla response. Klient może jedynie poinformować serwer, że będzie acceptkolekcją możliwych typów zawartości.

Definicje pól nagłówka

Pole Akceptuj nagłówek żądania może służyć do określania określonych typów nośników, które są akceptowane w odpowiedzi. Za pomocą nagłówków Accept można wskazać, że żądanie jest ograniczone do niewielkiego zestawu pożądanych typów, tak jak w przypadku żądania obrazu w linii.

Klient może zażądać obrazu image/jpeg, ale serwer odpowiada text/htmli kodem stanu, 404jeśli obraz nie został znaleziony. Serwery mogą również reagować niepoprawnie. Istnieje wiele witryn Wordpress, które odpowiadają text/htmlkodem stanu i nie wyszukują 200plików stron.

To wszystko jest ZŁA praktyka ze strony serwera. Próbuję ci powiedzieć, że jest to absolutnie możliwe i zdarza się często. Ludzie nie wiedzą, co robią, kiedy konfigurują te rzeczy.

Referencje będą mile widziane. Jak rozwiązać tę sytuację z komercyjnego punktu widzenia?

Wystąpił ten problem w kilku projektach. Dostajesz postdane JSON do serwera, a ono zwraca odpowiedź JSON lub HTML.

Naprawdę nie jest wielkim problemem wiedzieć, który typ był w odpowiedzi. Jeśli pierwszym znakiem jest {lub [możesz założyć JSON. Jeśli tak, <możesz założyć HTML. Tak sobie z tym poradziłem w przeszłości. Czasami programista, który napisał API, wie wszystko o nagłówkach HTTP. Wszystko powraca jako text/htmlodpowiedzi. Jeśli masz szczęście, mają Apache skonfigurowane domyślnie, text/plainco może czasem pomóc.

Te problemy istnieją i będą istnieć w dalekiej przyszłości. Komunikacja między serwerami to zdecydowanie nieuregulowane działanie. Nie ma organu zarządzającego, który wyrzuciłby sprzedawcę ze związku dla serwera, który udziela złych odpowiedzi HTTP.

Reactgular
źródło
Jest to zgodne z odpowiedzią @Marjan Venema, ale kolejną kluczową kwestią, którą poruszasz, jest dokumentacja tego zachowania. Aby dodać mojej frustracji, sprzedawca nie udokumentował tego zachowania. Typ zawartości różni się w zależności od stanu sesji, ale udokumentowana jest tylko odpowiedź JSON.
phillip.darley