Est-il correct de retourner du HTML à partir d'une API JSON?

25

Dans mon projet actuel, je suis responsable de la mise en œuvre d'un service qui implique la consommation d'API RESTful nouvellement créées, documentées comme prenant uniquement en charge JSON.

Le client fait régulièrement des demandes avec l'en-tête d'acceptation «application / json» et le type de contenu «application / json». Cependant, certains points de terminaison envoient une réponse avec un type de contenu HTML, même un corps HTML. Pour moi, c'est clairement la mauvaise approche et ne peut jamais être justifiée.

Tout au long du projet, cette même pratique a été appliquée à deux fournisseurs différents et à deux services différents. Je me suis retrouvé à devoir justifier pourquoi les services devaient être modifiés. Les fournisseurs ont déclaré que le client devrait faire face à cela et même ma bibliothèque REST de choix a été remise en question (RestEasy) car elle ne fait pas face à cela par défaut 'out the box'.

Cela a été un point de frustration majeur. Je ne trouve pas beaucoup de références pour étayer mon argument, je suppose que c'est parce que le point est théorique, car il est si évident.

La question est, est-ce que je manque quelque chose? suis-je pédant à ce sujet? Est-il correct d'avoir une API JSON qui n'a pas de type de contenu d'application / json dans ce scénario? Des références seraient appréciées. Comment résolvez-vous cette situation d'un point de vue commercial?

phillip.darley
la source
1
Par type de contexte, entendez-vous l'en-tête HTTP de type de contenu?
Marjan Venema
Oui, je me réfère à l'en-tête de type de contenu HTTP. Édité.
phillip.darley
Eh bien, au moins, ils ne doivent pas l'appeler une "API REST JSON" lorsqu'il s'agit d'une API HTML REST.
Bergi

Réponses:

28

Lorsque vous envoyez un en- accepttête demandant un type de média spécifique, le serveur ne doit pas renvoyer autre chose, et certainement pas avec un code d'état 200 OK

De Restpatterns.org :

Si aucun champ d'en-tête Accept n'est présent, il est supposé que le client accepte tous les types de supports. Si un champ d'en-tête Accept est présent, et si le serveur ne peut pas envoyer une réponse qui est acceptable selon la valeur combinée du champ Accept, alors le serveur DEVRAIT envoyer une réponse 406 (non acceptable).

(Souligner le mien)

Restpatterns.org prend cela du standard HTTP réel: Définitions des champs d'en-tête - Accepter

En bref: vous n'êtes pas pédant. Les services ne suivent pas la norme HTTP s'ils renvoient du HTML lorsque l'en-tête accept leur dit spécifiquement de revenir application/jsonet rien d'autre.

Marjan Venema
la source
1
+1. Je suis d'accord avec cette réponse, mais malheureusement, le mot shouldest utilisé à plusieurs reprises dans les spécifications HTTP. Nous devons lancer une pétition en ligne pour que ces mots soient remplacés par must.
Reactgular
3
@MarjanVenema "should" est correct car dans la section 10 du même rfc il y a une note: "Les serveurs HTTP / 1.1 sont autorisés à retourner des réponses qui ne sont pas acceptables selon les en-têtes accept envoyés dans la demande. Dans certains cas, cela peut même être préférable à l'envoi d'une réponse 406. "
imel96
1
Si un client demande une ressource qui n'a vraiment pas de représentation JSON, peu importe combien il veut JSON, il est peut-être préférable de recevoir autre chose qui est définitif; vous n'êtes pas assuré d'obtenir un 406. L'important est que le serveur décrive le type de contenu de la réponse.
Donal Fellows
6
@DonalFellows: Non, il vaudrait mieux qu'ils soient informés de ce qui est réellement le cas. Le serveur ne doit pas simplement renvoyer tout ce qu'il juge approprié, mais envoyer une réponse 406 non acceptable comme indiqué dans la norme. Gardez à l'esprit que lorsque le client demande spécifiquement un type de média et ne spécifie aucune solution de rechange, il n'a probablement aucun moyen de traiter un autre type de média.
Marjan Venema
2
@ imel96: le fait qu'Internet n'a jamais été strict est exactement ce qui a conduit à des difficultés à prendre en charge divers navigateurs et à des serveurs maintenant contraints de rester rétrocompatibles avec le html non valide car il y en a tout simplement trop. (et malheureusement, il est toujours en cours de création).
Marjan Venema
9

Que voulez-vous dire par «API JEST RESTful» - Je pense que le premier problème ici est que vous mélangez des concepts (ou peut-être quelqu'un entre vous et vos homologues techniques chez vos «fournisseurs»).

Une API RESTful (que vous ne parliez pas du tout vraiment au niveau 1 ou quelque chose au niveau 3 ou supérieur cf http://martinfowler.com/articles/richardsonMaturityModel.html ) concerne la façon dont vous interagissez avec l'API, pas le format du contenu envoyé ou reçu de. Il ne s'agit même pas de protocoles ou de mécanismes de transport ...

De même, une API JSON est une API qui prend en charge l'utilisation de JSON comme format de données - elle peut ou non être reposante, elle peut ou non être implémentée à l'aide de HTTP et (et c'est le point clé) elle peut ou non prendre en charge JSON exclusivement.

Une bonne API fonctionnant sur HTTP (il est raisonnable de supposer que dans le contexte vous parlez d'une API exposée sur HTTP) devrait vous permettre de demander du contenu dans une variété de formats et ces formats peuvent (et devraient éventuellement) inclure HTML ainsi que JSON et XML. Pourquoi? Eh bien, cela rendrait l'apprentissage de l'API beaucoup plus facile, conceptuellement, il fournit une UX basée sur un navigateur instantané pour n'importe quel but et ainsi de suite ...

La question intéressante devient alors si mon API, qui prend en charge une variété de formats de contenu, est appelée sans qu'on lui dise quel format le client attend alors quel format doit-elle retourner ...? Cela tend vers un argument religieux - mais HTML donne au fournisseur la possibilité d'inclure des informations utiles (comme "n'oubliez pas de définir l'en-tête accepter le contenu").

Pour répondre à la question, une API, une qui est reposante et une qui prend en charge json, doit absolument pouvoir retourner du HTML si c'est le contenu demandé.

Murph
la source
1
Je prends vos deux points et j'ai modifié ma question en conséquence. Le fait que le service soit RESTful n'est pas pertinent et j'ai détaillé que le client accepte 'application / json' dans chaque demande.
phillip.darley
Je dirais que «API JEST RESTful» a une signification très évidente.
gnasher729
1
Je dirais que mes professeurs ont déployé énormément d'efforts pour s'assurer que nous comprenions pourquoi «ne jamais supposer» était un élément clé pour être un bon programmeur
Murph
5

Le client fait régulièrement des demandes avec l'en-tête d'acceptation «application / json» et le type de contenu «application / json»

Oui, c'est la bonne chose à faire, mais cela ne signifie pas que le vendeur s'en soucie. Bien que je comprenne totalement votre frustration, car je pense également qu'un service JSON devrait toujours donner une réponse JSON, mais il existe de nombreux exemples où ce n'est pas le cas.

Tout au long du projet, cette même pratique a été appliquée à deux fournisseurs différents et à deux services différents. Je me suis retrouvé à devoir justifier pourquoi les services devaient être modifiés. Les fournisseurs ont déclaré que le client devrait faire face à cela et même ma bibliothèque REST de choix a été remise en question (RestEasy) car elle ne fait pas face à cela par défaut 'out the box'.

Eh bien, je dois être d'accord avec le vendeur. C'est leur service et tant qu'ils documentent clairement les cas particuliers d'utilisation, vous ne pouvez pas vraiment leur imposer de le changer. C'est un inconvénient pour eux, car les développeurs seront lents à adopter leur API, et s'ils écoutaient ce dont les développeurs ont besoin, ils le changeraient, mais malheureusement, il n'y a pas de règle selon laquelle ils doivent suivre les normes.

La question est-ce que je manque quelque chose?

Les en-têtes de demande ne signifient rien sauf s'ils sont correctement interrompus à l'autre extrémité. Je sais que si je développe une API web en utilisant PHP, alors au diable les en-têtes de requête. Je peux répondre avec tout ce que je veux. Alors qu'un service configuré dans IIS avec C # offre une gestion beaucoup plus facile des en-têtes de demande, de leur type et du type de réponse. Cela a beaucoup à voir avec les outils utilisés par le fournisseur pour créer l'API.

Je suis pédant à ce sujet?

Oui et non. J'ai des amis développeurs qui ne pourraient pas passer outre. Ils deviendraient tellement obsédés par le problème et incapables de poursuivre d'autres tâches jusqu'à ce que l'API fonctionne comme ils l'attendent. Maintenant c'est pédant.

C'est un problème car le fournisseur a créé "plus de travail" pour terminer vos tâches. N'importe qui en serait frustré. Je sais que je le serais.

Est-il correct d'avoir une API JSON qui n'a pas de type de contenu d'application / json dans ce scénario?

Absolument, mais ce n'est pas une bonne pratique.

Un client ne peut dire au serveur que le type de contexte d'un request. Il n'a pas la possibilité d'appliquer un type de contenu pour le response. Le client peut seulement informer le serveur qu'il disposera d' acceptune collection de types de contenu possibles.

Définitions des champs d'en-tête

Le champ En-tête de demande d'acceptation peut être utilisé pour spécifier certains types de supports acceptables pour la réponse. Accepter les en-têtes peut être utilisé pour indiquer que la demande est spécifiquement limitée à un petit ensemble de types souhaités, comme dans le cas d'une demande d'image en ligne.

Il est possible pour un client de demander une image de image/jpeg, mais le serveur répond avec text/htmlet un code d'état 404si l'image n'est pas trouvée. Les serveurs peuvent également répondre incorrectement. Il existe de nombreux sites Web Wordpress qui répondent avec un text/htmlcode d'état 200pour les pages non trouvées.

Maintenant, c'est toute la mauvaise pratique de la part du serveur. Ce que j'essaie de vous dire, c'est que c'est absolument possible, et ça arrive souvent. Les gens ne savent pas ce qu'ils font lorsqu'ils configurent ces choses.

Des références seraient appréciées. Comment résolvez-vous cette situation d'un point de vue commercial?

J'ai rencontré ce problème sur quelques projets. Vous postdonnez des données JSON au serveur et cela donne une réponse JSON ou HTML.

Ce n'est vraiment pas un gros problème de savoir quel type était dans la réponse. Si le premier caractère est {ou [vous pouvez supposer JSON. Si c'est le cas, <vous pouvez assumer HTML. Voilà comment je l'ai géré dans le passé. Parfois, le programmeur qui a écrit l'API sait tout sur les en-têtes HTTP. Tout revient comme text/htmlréponses. Si vous avez de la chance, Apache est configuré par défaut, text/plaince qui peut parfois aider.

Ces problèmes existent et continueront d'exister dans le futur. La communication de serveur à serveur est de loin une activité non réglementée. Il n'y a pas d'organe directeur qui expulsera un fournisseur d'une union pour un serveur qui donne de mauvaises réponses HTTP.

Reactgular
la source
Cela correspond à la réponse de @Marjan Venema mais un autre point clé que vous soulevez est la documentation de ce comportement. Pour ajouter à ma frustration, le fournisseur n'a pas documenté ce comportement. Le type de contenu varie en fonction de l'état de la session, mais seule la réponse JSON est documentée.
phillip.darley