web-dev-qa-db-fra.com

Réponse de 400 vs 422 à POST des données

J'essaie de déterminer le code de statut correct à renvoyer dans différents scénarios avec une API "de type REST" sur laquelle je travaille. Disons que j'ai un point final qui permet d'effectuer des achats POST au format JSON. Cela ressemble à ceci:

{
    "account_number": 45645511,
    "upc": "00490000486",
    "price": 1.00,
    "tax": 0.08
}

Que dois-je retourner si le client m'envoie "sales_tax" (au lieu de la "taxe" attendue). Actuellement, je retourne un 400. Mais, j'ai commencé à me poser des questions à ce sujet. Devrais-je vraiment retourner un 422? Je veux dire, c'est JSON (qui est supporté) et c'est un JSON valide, il ne contient tout simplement pas tous les champs obligatoires.

313
David S

400 Bad Request semblerait maintenant être le meilleur code d'état HTTP/1.1 pour votre cas d'utilisation.

Au moment de votre question (et ma réponse originale), RFC 7231 n'était pas une chose; à quel point je me suis opposé à 400 Bad Request parce que RFC 2616 a dit (avec une emphase le mien):

La requête n'a pas pu être comprise par le serveur en raison d'une syntaxe mal formée .

et la demande que vous décrivez est un JSON syntaxiquement valide encapsulé dans un HTTP syntaxiquement valide. Le serveur n'a donc aucun problème avec la syntaxe de la demande.

Cependant comme l'a souligné Lee Saferite dans les commentaires , La RFC 7231, qui rend obsolète la RFC 2616, ne inclure cette restriction :

Le code d’état 400 (demande incorrecte) indique que le serveur ne peut pas ou ne traitera pas la demande en raison d’une erreur perçue par le client (par exemple, syntaxe de demande malformée, cadrage du message de demande non valide ou acheminement trompeur de demande).


Cependant, avant cette reformulation (ou si vous voulez critiquer la RFC 7231 comme étant une norme proposée pour le moment ), 422 Unprocessable Entity ne semble pas être un incorrect ​​Code de statut HTTP pour votre cas d'utilisation, car l'introduction à la RFC 4918 indique:

Bien que les codes d'état fournis par HTTP/1.1 soient suffisants pour décrire la plupart des conditions d'erreur rencontrées par les méthodes WebDAV, certaines erreurs ne tombent pas clairement dans les catégories existantes. Cette spécification définit des codes d’état supplémentaires développés pour les méthodes WebDAV (Section 11)

Et la description de 422 dit:

Le code d’état 422 (entité non traitable) signifie que le serveur comprend le type de contenu de l’entité de demande (par conséquent, un code d’état 415 (type de support non supporté) est inapproprié), et la syntaxe de l’entité de demande est correcte (donc, une requête 400 (requête incorrecte)). ) le code d’état est inapproprié) mais n’a pas pu traiter les instructions contenues.

(Notez la référence à la syntaxe; je soupçonne que 7231 est en partie obsolète par 4918 également)

Cela ressemble exactement ​​à votre situation, mais juste au cas où il y aurait un doute, cela continue:

Par exemple, cette condition d'erreur peut se produire si un corps de requête XML contient des instructions XML bien formées (c'est-à-dire syntaxiquement correctes), mais sémantiquement erronées.

(Remplacez "XML" par "JSON" et je pense que nous pouvons convenir de votre situation.)

Maintenant, certains objecteront que la RFC 4918 est à propos des "extensions HTTP pour la création et la gestion de versions Web (WebDAV)" et que vous (supposément) ne faites rien avec WebDAV, vous ne devriez donc pas en utiliser les éléments.

Étant donné le choix entre utiliser un code d'erreur dans la norme d'origine qui ne couvre pas explicitement la situation et un code provenant d'une extension décrivant exactement la situation, je choisirais la dernière.

En outre, RFC 4918, section 21.4 fait référence au registre du code d'état du protocole de transfert hypertexte IANA (HTTP) , où 422 peut être trouvé.

Je propose qu'il soit tout à fait raisonnable qu'un client ou un serveur HTTP utilise n'importe quel code d'état de ce registre, à condition qu'il le fasse correctement.


Mais à partir de HTTP/1.1, RFC 7231 a de la traction, utilisez donc simplement 400 Bad Request!

375
Kristian Glass

Pour refléter le statut à partir de 2015:

Les codes de réponse 400 et 422 seront traités de la même manière par les clients et les intermédiaires. Par conséquent, cela ne fait pas une différence concrète que vous utilisez.

Cependant, je m'attendrais à ce que 400 soient actuellement utilisés plus largement, et les précisions apportées par HTTPbis spec en font le plus approprié des deux codes d'état:

  • La spécification HTTPbis clarifie l’intention de 400 de ne pas être uniquement destinée aux erreurs de syntaxe. L'expression plus large "indique que le serveur ne peut pas ou ne traitera pas la demande en raison d'une erreur perçue par le client" est maintenant utilisée.
  • 422 Est spécifiquement une extension WebDAV et n'est pas référencé dans la RFC 2616 ou dans la nouvelle version spécification HTTPbis .

Pour le contexte, HTTPbis est une révision de la spécification HTTP/1.1 qui tente de clarifier les zones peu claires ou incohérentes. Une fois approuvé, il remplacera le RFC2616.

32
Tom Christie

400 Bad Request est le code de statut HTTP approprié pour votre cas d'utilisation. Le code est défini par HTTP/0.9-1.1 RFC.

La requête n'a pas pu être comprise par le serveur en raison d'une syntaxe mal formée. Le client NE DEVRAIT PAS répéter la demande sans modifications.

http://tools.ietf.org/html/rfc2616#section-10.4.1

422 L'entité non traitable est définie par RFC 4918 - WebDav. Notez qu'il existe une légère différence par rapport à 400, voir le texte cité ci-dessous.

Cette condition d'erreur peut se produire si un corps de demande XML contient des instructions XML bien formées (c'est-à-dire syntaxiquement correctes), mais sémantiquement erronées.

Pour conserver une interface uniforme, vous ne devez utiliser 422 que dans le cas de réponses XML et vous devez également prendre en charge tous les codes d'état définis par l'extension Webdav, pas seulement 422.

http://tools.ietf.org/html/rfc4918#page-78

Voir aussi l'article de Mark Nottingham sur les codes d'état:

c’est une erreur d’essayer de mapper chaque partie de votre application "en profondeur" en codes d’état HTTP; dans la plupart des cas, le niveau de granularité que vous souhaitez atteindre est beaucoup plus grossier. En cas de doute, vous pouvez utiliser les codes d’état génériques 200 OK, 400 Requête incorrecte et 500 Erreur de service interne s’il n’ya pas de meilleur ajustement .

Comment penser aux codes de statut HTTP

31
filip26

Il n'y a pas de réponse correcte, car cela dépend de la définition de la "syntaxe" pour votre requête. La chose la plus importante est que vous:

  1. Utilisez le (s) code (s) de réponse de manière cohérente
  2. Incluez autant d'informations supplémentaires que possible dans le corps de la réponse pour aider le ou les développeurs à l'aide de votre API à comprendre ce qui se passe.

Avant que tout le monde me saute dessus pour dire qu'il n'y a pas de bonne ou de mauvaise réponse ici, laissez-moi vous expliquer un peu comment j'ai abouti à la conclusion.

Dans cet exemple spécifique, la question de l'OP concerne une requête JSON contenant une clé différente de celle attendue. Maintenant, le nom de clé reçu est très similaire, du point de vue du langage naturel, à la clé attendue, mais il est strictement différent, et donc pas (généralement) reconnu par une machine comme étant équivalent.

Comme je l'ai dit plus haut, le facteur déterminant est ce que l'on entend par syntaxe. Si la demande a été envoyée avec un type de contenu de application/json, alors oui, la demande est syntaxiquement valide car sa syntaxe JSON est valide, mais pas sémantiquement valide, car cela ne correspond pas à ce qui est attendu. (en supposant une définition stricte de ce qui rend la requête en question sémantiquement valide ou non).

Si, par contre, la demande était envoyée avec un type de contenu personnalisé plus spécifique, tel que application/vnd.mycorp.mydatatype+json, spécifiant peut-être exactement quels champs étaient attendus, je dirais que la demande pourrait facilement être syntaxiquement non valide, d'où 400 réponses.

Dans le cas en question, puisque le clé était erroné, pas le valeur, il y avait un syntaxe erreur s'il y avait un spécification pour ce que sont les clés valides. S'il n'y avait pas de spécification pour les clés valides, ou l'erreur était avec une valeur, alors ce serait une erreur sémantique.

14
cdeszaq

Étude de cas: API GitHub

https://developer.github.com/v3/#client-errors

Peut-être que copier à partir d’API bien connues est une bonne idée:

Il existe trois types d'erreur de client possibles sur les appels d'API recevant le corps de la demande:

L'envoi de JSON non valide entraînera une réponse de 400 demandes incorrectes.

HTTP/1.1 400 Bad Request
Content-Length: 35

{"message":"Problems parsing JSON"}

L'envoi d'un type de valeur JSON incorrect entraînera une réponse de 400 demandes incorrectes.

HTTP/1.1 400 Bad Request
Content-Length: 40

{"message":"Body should be a JSON object"}

L'envoi de champs non valides entraînera une réponse 422 non traitable.

HTTP/1.1 422 Unprocessable Entity
Content-Length: 149

{
  "message": "Validation Failed",
  "errors": [
    {
      "resource": "Issue",
      "field": "title",
      "code": "missing_field"
    }
  ]
}

422 Entité non traitable expliquée Mise à jour: 6 mars 2017

Qu'est-ce qu'une entité non traitable?

Un code d'état 422 apparaît lorsqu'une demande est bien formée. Cependant, en raison d'erreurs sémantiques, il est impossible de la traiter. Ce statut HTTP a été introduit dans la RFC 4918 et vise plus particulièrement les extensions HTTP pour WebDD (Web Distributed Authoring and Versioning).

Il existe une certaine controverse sur le point de savoir si les développeurs doivent ou non renvoyer une erreur 400 vs 422 aux clients (plus de détails sur les différences entre les deux statuts ci-dessous). Toutefois, dans la plupart des cas, il est convenu que le statut 422 ne doit être renvoyé que si vous prenez en charge les fonctionnalités WebDAV.

Une définition mot à mot du code d'état 422 tiré de la section 11.2 de la RFC 4918 peut être lue ci-dessous.

Le code d’état 422 (entité non traitable) signifie que le serveur comprend le type de contenu de l’entité de demande (par conséquent, un code d’état 415 (type de support non supporté) est inapproprié), et la syntaxe de l’entité de demande est correcte (donc, une requête 400 (requête incorrecte)). ) le code d’état est inapproprié) mais n’a pas pu traiter les instructions contenues.

La définition se poursuit comme suit:

Par exemple, cette condition d'erreur peut se produire si un corps de requête XML contient des instructions XML bien formées (c'est-à-dire syntaxiquement correctes), mais sémantiquement erronées.

Codes de statut 400 vs 422

Les erreurs de requête incorrectes utilisent le code d'état 400 et doivent être renvoyées au client si la syntaxe de la requête est mal formée, contient un encadrement de message de requête non valide ou présente un acheminement de requête trompeur. Ce code de statut peut sembler assez similaire au statut 422 d'entité non traitable, cependant, une petite information qui les distingue est le fait que la syntaxe d'une entité de requête pour une erreur 422 est correcte alors que la syntaxe d'une requête qui génère l'erreur est incorrecte.

L'utilisation du statut 422 ne devrait être réservée qu'à des cas d'utilisation très particuliers. Dans la plupart des autres cas où une erreur client s'est produite en raison d'une syntaxe mal formée, le statut 400 demandes incorrectes doit être utilisé.

https://www.keycdn.com/support/422-unprocessable-entity/

4
Clojurevangelist

Tout d'abord, c'est une très bonne question.

400 Bad Request - Lorsqu'un élément critique manque dans la demande

par exemple. En-tête d'autorisation ou en-tête de type de contenu. Ce qui est absolument requis par le serveur pour comprendre la requête. Cela peut différer d'un serveur à l'autre.

422 Entité non traitable - Lorsque le corps de la demande ne peut pas être analysé.

C'est moins grave que 400. La demande a atteint le serveur. Le serveur a accusé réception de la demande et obtenu la structure de base correcte. Toutefois, les informations contenues dans le corps de la demande ne peuvent être ni analysées ni comprises.

par exemple. Content-Type: application/xml lorsque le corps de la demande est JSON.

Voici un article répertoriant les codes d'état et son utilisation dans les API REST. https://metamug.com/article/status-codes-for-rest-api.php

2
user8029840

Votre cas: HTTP 400 est le bon code de statut pour votre cas de la perspective REST, car sa syntaxe est incorrecte pour envoyer sales_tax au lieu de tax, bien que ce soit un JSON valide. Ceci est normalement appliqué par la plupart des infrastructures côté serveur lors du mappage du JSON aux objets. Cependant, certaines implémentations REST ignorent le nouveau key dans l'objet JSON. Dans ce cas, une spécification personnalisée content-type acceptant uniquement les champs valides peut être appliquée par le serveur.

Scénario idéal pour 422:

Dans un monde idéal, 422 est préférable et généralement acceptable pour l'envoi en réponse si le serveur comprend le type de contenu de l'entité de demande et la syntaxe de la demande. L'entité est correcte mais n'a pas pu traiter les données car celles-ci étaient sémantiquement erronées.

Situations de 400 à 422:

N'oubliez pas que le code de réponse 422 est un code d'état HTTP étendu (WebDAV). Certains clients HTTP/bibliothèques frontales ne sont pas prêts à gérer 422. Pour eux, c'est aussi simple que "HTTP 422 est faux, car ce n'est pas HTTP" . Du point de vue du service, 400 n’est pas tout à fait spécifique.

Dans l'architecture d'entreprise, les services sont principalement déployés sur des couches de services telles que SOA, IDM, etc. Ils desservent généralement plusieurs clients, allant d'un très ancien client natif à un dernier client HTTP. Si l'un des clients ne gère pas HTTP 422, les options sont les suivantes: demander au client de mettre à niveau ou de modifier votre code de réponse en HTTP 400 pour tout le monde. D'après mon expérience, c'est très rare ces jours-ci, mais cela reste une possibilité. Donc, une étude minutieuse de votre architecture est toujours nécessaire avant de choisir les codes de réponse HTTP.

Pour gérer de telles situations, les couches de service utilisent normalement l'indicateur versioning ou setup configuration pour que les clients à la conformité HTTP stricte envoient 400, et 422 pour le reste. De cette manière, ils offrent un support de compatibilité ascendante aux consommateurs existants tout en offrant la possibilité aux nouveaux clients de consommer HTTP 422.


La dernière mise à jour de RFC7321 dit:

The 400 (Bad Request) status code indicates that the server cannot or
   will not process the request due to something that is perceived to be
   a client error (e.g., malformed request syntax, invalid request
   message framing, or deceptive request routing).

Cela confirme que les serveurs peuvent envoyer HTTP 400 pour une requête non valide. 400 ne fait plus seulement référence à une erreur de syntaxe , toutefois, 422 est toujours une réponse authentique, à condition que les clients puissent la gérer.

1
YuVi