Réponse de 400 vs 422 au POST de données


356

J'essaie de déterminer le code d'état correct à retourner dans différents scénarios avec une API "REST-like" sur laquelle je travaille. Disons que j'ai un point final qui permet de poster des achats 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. Dois-je vraiment retourner un 422? Je veux dire, c'est JSON (qui est pris en charge) et c'est JSON valide, il ne contient tout simplement pas tous les champs obligatoires.


Réponses:


419

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

Au moment de votre question (et de ma réponse d'origine), la RFC 7231 n'était pas une chose; auquel point je me suis opposé 400 Bad Requestparce que la RFC 2616 a dit (avec emphase la mienne):

La demande n'a pas pu être comprise par le serveur en raison d'une syntaxe incorrecte .

et la demande que vous décrivez est un JSON syntaxiquement valide enfermé dans un HTTP syntaxiquement valide, et donc le serveur n'a 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, n'inclut pas cette restriction :

Le code d'état 400 (Bad Request) indique que le serveur ne peut pas ou ne traitera pas la demande en raison de quelque chose qui est perçu comme une erreur client (par exemple, une syntaxe de demande incorrecte, un cadrage de message de demande invalide ou un routage de demande trompeur).


Cependant, avant cette reformulation (ou si vous voulez ergoter sur le fait que la RFC 7231 n'est actuellement qu'une norme proposée ), 422 Unprocessable Entityne semble pas un code d'état HTTP incorrect pour votre cas d'utilisation, car comme le dit l'introduction de la RFC 4918:

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 parfaitement 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 de422 dit:

Le code d'état 422 (entité non traitable) signifie que le serveur comprend le type de contenu de l'entité de demande (donc un code d'état 415 (type de support non pris en charge) est inapproprié) et la syntaxe de l'entité de demande est correcte (donc 400 (mauvaise demande) ) 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 obsolète en partie 4918 aussi)

Cela ressemble exactement à votre situation, mais juste au cas où il y aurait un doute, il 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 que c'est votre situation)

Maintenant, certains objecteront que la RFC 4918 concerne les «extensions HTTP pour la création et la version distribuées sur le Web (WebDAV)» et que vous (vraisemblablement) ne faites rien impliquant WebDAV, vous ne devriez donc pas en utiliser les éléments.

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

En outre, la section 21.4 de la RFC 4918 fait référence au registre de code d'état HTTP (Hypertext Transfer Protocol) de l' IANA , où se trouve 422.

Je propose qu'il soit tout à fait raisonnable pour un client ou un serveur HTTP d'utiliser n'importe quel code d'état de ce registre, tant qu'ils le font correctement.


Mais à partir de HTTP / 1.1, le RFC 7231 a une traction, alors utilisez-le 400 Bad Request!


5
Votre réponse (422) est logique pour moi. C'est également ce que Rails ( respond_with ) utilise lorsqu'une ressource n'a pas pu être traitée en raison d'erreurs de validation.
Tyler Rick

11
Notez l'utilisation de 422 dans les spécifications non WebDAV ici: tools.ietf.org/html/rfc5789#section-2.2
Andrey Shchekin

4
Tout comme une mise à jour, RFC 7231 a une description différente pour le code de réponse 400 qui change la sémantique.
Lee Saferite

5
Mes excuses - j'ai mis à jour cette réponse pour refléter le changement dans les RFC et perdu un peu de clarté; Je vais essayer de refactoriser. Il est presque certainement sûr d'utiliser le 422, mais de nos jours vous devriez en utiliser le 400.
Kristian Glass

2
Je pense toujours que la spécification pourrait être beaucoup plus claire. Les exemples donnés dans le sont des cas clairs du client faisant quelque chose de mal. La situation du PO entre également dans cette catégorie. Cependant, il y a des cas comme "je comprends ce que vous demandez, mais je refuse de le faire parce qu'il y a une règle commerciale contre cela" n'est pas si clair. Ce n'est pas exactement la faute du client, donc un 403 pourrait effectivement s'appliquer, selon la même spécification: "Cependant, une demande peut être interdite pour des raisons sans rapport avec les informations d'identification". Je préférerais cependant avoir des codes séparés pour les trucs liés aux autorisations et "cela ne peut pas être fait".
Thorarin

38

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

La demande n'a pas pu être comprise par le serveur en raison d'une syntaxe incorrecte. 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 la RFC 4918 - WebDav. Notez qu'il y a 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 requête XML contient des instructions XML bien formées (c'est-à-dire syntaxiquement correctes) mais sémantiquement erronées.

Pour conserver une interface uniforme, vous devez utiliser 422 uniquement dans le cas des 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 le post de Mark Nottingham sur les codes de statut:

c'est une erreur d'essayer de mapper chaque partie de votre application "profondément" en codes d'état HTTP; dans la plupart des cas, le niveau de granularité que vous souhaitez viser est beaucoup plus grossier. En cas de doute, vous pouvez utiliser les codes d'état génériques 200 OK, 400 Bad Request et 500 Internal Service Error lorsqu'il n'y a pas de meilleur ajustement .

Comment penser aux codes d'état HTTP


4
Le code 422 fait partie du registre IANA iana.org/assignments/http-status-codes/http-status-codes.xhtml donc toute IMHO n'a aucun sens. Dans tous les cas, Facebook et Twitter REST API réinventent leurs propres codes et n'utilisent pas les normes RFC / IANA. Vous pouvez donc le faire.
gavenkoa

15
La section 11 indique spécifiquement qu'ils sont ajoutés à la spécification entière et pas seulement dans la spécification WebDav:The following status codes are added to those defined in HTTP/1.1 [RFC2616].
Steve Tauber

8
Ce n'est pas parce que le code est décrit comme faisant partie de la spécification WebDAV qu'il est spécifique à WebDAV! Les codes d'état sont censés être génériques.
traitez bien vos mods le

33

Pour refléter l'état d'avancement en 2015:

D'un point de vue comportemental, les codes de réponse 400 et 422 seront traités de la même manière par les clients et les intermédiaires, donc cela ne fait en fait aucune différence concrète que vous utilisez.

Cependant, je m'attends à voir 400 actuellement plus largement utilisés, et en outre les clarifications que la spécification HTTPbis fournit en font le plus approprié des deux codes de statut:

  • La spécification HTTPbis clarifie l'intention de 400 pour ne pas être uniquement pour les erreurs de syntaxe. L'expression plus large "indique que le serveur ne peut pas ou ne traitera pas la demande en raison de quelque chose qui est perçu comme une erreur client" est désormais utilisée.
  • 422 Est spécifiquement une extension WebDAV et n'est pas référencée dans la RFC 2616 ou dans la spécification HTTPbis plus récente .

Pour le contexte, HTTPbis est une révision de la spécification HTTP / 1.1 qui tente de clarifier les domaines qui n'étaient pas clairs ou incohérents. Une fois qu'il aura atteint le statut approuvé, il remplacera la RFC2616.


4
Le 403 Forbidden ne pourrait-il pas également être utilisé dans ce contexte? Quote: Le code d'état 403 (interdit) indique que le serveur a compris la demande mais refuse de l'autoriser ... Si les informations d'authentification ont été fournies dans la demande, le serveur les considère insuffisantes pour accorder l'accès .... Cependant, une demande peut être interdit pour des raisons sans rapport avec les pouvoirs. Il semble donc que 403 puisse être utilisé pour rejeter les demandes en dehors de l'authentification.
garbagecollector

1
@garbagecollector note que "rejeté pour des raisons en dehors des informations d' identification "! = "rejeté pour des raisons en dehors de l' authentification ". Il existe de nombreuses façons d'authentifier quelqu'un sans utiliser spécifiquement les informations d'identification.
Knetic

@garbagecollector non, les informations d'identification signifient l'authentification ("qui êtes-vous"), qui serait 401 en cas d'échec. L'autorisation («que pouvez-vous faire») serait de 403 en cas d'échec. Explication complète ici: stackoverflow.com/a/6937030/137948 Ni l'un ni l'autre ne s'applique à la situation des "champs manquants" de l'OP car l'erreur serait la même quel que soit l'utilisateur qui l'a tenté. Je suis d'accord 400 est la bonne réponse.
Will Sheppard

27

É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'erreurs client possibles sur les appels d'API qui reçoivent des corps de demande:

L'envoi d'un 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 du mauvais type de valeurs JSON entraînera une réponse 400 Bad Request.

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 de l'entité 422 non traitable.

HTTP/1.1 422 Unprocessable Entity
Content-Length: 149

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

Je pense que c'est la réponse correcte et compréhensible.
LEMUEL ADANE

1
Je ne peux pas voter plus. Je souhaite que des réponses plus votées se réfèrent à celle-ci. Les spécifications (RFC, IANA) n'ont pas réussi à fournir des définitions claires et une distinction claire entre les deux. La réponse se résume donc aux meilleures pratiques et GitHub nous en donne une.
Alex Klaus

15

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

  1. Utilisez le ou les codes 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 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, permettez-moi d'expliquer un peu comment je suis arrivé à la conclusion.

Dans cet exemple spécifique, la question de l'OP concerne une demande JSON qui contient 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écisif 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 c'est une syntaxe JSON valide, mais pas sémantiquement valide, car elle ne correspond pas à ce qui est attendu. (en supposant une définition stricte de ce qui rend la demande en question sémantiquement valide ou non).

Si, d'autre part, la demande a été envoyée avec un type de contenu personnalisé plus spécifique comme application/vnd.mycorp.mydatatype+jsoncelui-ci, peut-être, spécifie exactement quels champs sont attendus, alors je dirais que la demande pourrait facilement être syntaxiquement invalide, d'où la réponse 400.

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


Réponse très sous-estimée - merci pour l'explication bien formulée.
puiu

Exactement mes réflexions sur la question! Je viens de l'arrière-plan XML SOAP et le concept de schéma vient d'entrer dans mon sang et les documents JSON n'annoncent pas leur schéma. Pour moi, c'est si le serveur "comprend" la demande ou non. Si le serveur ne sait pas ce qu'est "taxe_vente", alors c'est simplement 400: "Je n'ai aucune idée de ce que vous m'avez envoyé mais certainement pas de ce que je veux.".
Aleksander Stelmaczonek

4

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

Qu'est-ce que l'entité 422 non traitable?

Un code d'état 422 se produit lorsqu'une demande est bien formée, cependant, en raison d'erreurs sémantiques, elle ne peut pas être traitée. Ce statut HTTP a été introduit dans la RFC 4918 et est plus spécifiquement destiné aux extensions HTTP pour la création et la gestion de versions distribuées Web (WebDAV).

Il existe une certaine controverse quant à savoir si les développeurs doivent renvoyer une erreur 400 vs 422 aux clients (plus d'informations sur les différences entre les deux états ci-dessous). Cependant, 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ée 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 (donc un code d'état 415 (type de support non pris en charge) est inapproprié) et la syntaxe de l'entité de demande est correcte (donc 400 (mauvaise demande) ) le code d'état est inapproprié) mais n'a pas pu traiter les instructions contenues.

La définition poursuit en disant:

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.

400 vs 422 codes d'état

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

L'utilisation du statut 422 ne doit ê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 incorrecte, le statut 400 Bad Request doit être utilisé.

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


1

Votre cas: HTTP 400 est le bon code d'état pour votre cas du point de vue REST car il est syntaxiquement incorrect à envoyer sales_taxau 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 les nouveaux keyobjets JSON. Dans ce cas, une content-typespécification personnalisée pour accepter uniquement les champs valides peut être appliquée côté serveur.

Scénario idéal pour 422:

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

Situations de 400 sur 422:

N'oubliez pas que le code de réponse 422 est un code d'état HTTP étendu (WebDAV). Il existe encore des clients HTTP / bibliothèques frontales qui 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 déployés principalement sur des couches de services comme SOA, IDM, etc. Ils servent 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 consistent à 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 de nos jours mais c'est toujours une possibilité. Ainsi, une étude minutieuse de votre architecture est toujours requise avant de décider des codes de réponse HTTP.

Pour gérer une telle situation, les couches de service utilisent versioningou configurent normalement un configurationindicateur pour que les clients de conformité HTTP stricte envoient 400 et envoient 422 pour le reste d'entre eux. De cette façon, ils fournissent une prise en charge de la compatibilité descendante pour les consommateurs existants, mais offrent en même temps la possibilité aux nouveaux clients de consommer HTTP 422.


La dernière mise à jour du RFC7321 indique:

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 demande non valide. 400 ne se réfère plus seulement à une erreur de syntaxe , cependant, 422 est toujours une réponse authentique à condition que les clients puissent la gérer.


1

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

400 Mauvaise demande - Lorsqu'une information critique manque dans la demande

Par exemple, l'en-tête d'autorisation ou l'en-tête du type de contenu. Ce qui est absolument requis par le serveur pour comprendre la demande. 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 reconnu que la demande avait la bonne structure de base. Mais les informations contenues dans le corps de la demande ne peuvent pas être analysées ou comprises.

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

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


5
422 signifie que la syntaxe est valide, mais le contenu ne l'est pas. L'envoi de JSON où XML est attendu signifie que la syntaxe est incorrecte, donc 400 est la bonne réponse dans ce cas.
Dirk

1
Exactement comme Dirk l'a dit 422 signifie une requête syntaxiquement valide (peut être analysée et comprise) mais sémantiquement invalide
Jacek Obarymski

400: lorsque la demande ne peut pas être traitée en raison d'une syntaxe non valide (par exemple, erreur d'analyse); 422: lorsque la demande ne peut pas être traitée en raison de données non valides (par exemple, erreur de validation).
Kitanotori

Votre exemple pour 422 n'est pas valide car en envoyant json avec un type de média application / xml, le corps est automatiquement syntaxiquement incorrect et la réponse doit être 400.
manemarron

-15

Vous devez en fait retourner "200 OK" et inclure dans le corps de la réponse un message sur ce qui s'est passé avec les données publiées. Ensuite, c'est à votre application de comprendre le message.

Le truc, c'est que les codes d'état HTTP sont exactement cela - des codes d'état HTTP. Et ceux-ci sont censés avoir un sens uniquement au niveau de la couche transport, pas au niveau de la couche application. La couche application ne devrait vraiment jamais savoir que HTTP est utilisé. Si vous avez changé votre couche de transport de HTTP à Pigeons voyageurs, cela ne devrait en aucun cas affecter votre couche d'application.

Permettez-moi de vous donner un exemple non virtuel. Disons que vous tombez amoureux d'une fille et qu'elle vous aime en retour, mais sa famille déménage dans un pays complètement différent. Elle vous donne sa nouvelle adresse e-mail. Naturellement, vous décidez de lui envoyer une lettre d'amour. Vous écrivez donc votre lettre, la mettez dans une enveloppe, écrivez son adresse sur l'enveloppe, y apposez un tampon et l'envoyez. Examinons maintenant ces scénarios

  1. Vous avez oublié d'écrire un nom de rue. Vous recevrez une lettre non ouverte avec un message écrit indiquant que l'adresse est incorrecte. Vous avez foiré la demande et le bureau de poste destinataire n'est pas en mesure de la traiter. C'est l'équivalent de recevoir "400 Bad Request".
  2. Vous fixez donc l'adresse et renvoyez la lettre. Mais à cause de la malchance, vous avez totalement mal orthographié le nom de la rue. Vous recevrez à nouveau la lettre avec un message disant que l'adresse n'existe pas. C'est l'équivalent de recevoir "404 Not Found".
  3. Vous fixez à nouveau l'adresse et cette fois, vous parvenez à écrire l'adresse correctement. Votre fille reçoit la lettre et vous répond. C'est l'équivalent de recevoir "200 OK". Cependant, cela ne signifie pas que vous aimerez ce qu'elle a écrit dans sa lettre. Cela signifie simplement qu'elle a reçu votre message et qu'elle a une réponse pour vous. Jusqu'à ce que vous ouvriez l'enveloppe et lisez sa lettre, vous ne pouvez pas savoir si elle vous manque beaucoup ou si elle veut rompre avec vous.

En bref: renvoyer "200 OK" ne signifie pas que l'application serveur a de bonnes nouvelles pour vous. Cela signifie seulement qu'il a des nouvelles.

PS: Le code d'état 422 n'a de signification que dans le contexte de WebDAV. Si vous ne travaillez pas avec WebDAV, alors 422 a exactement la même signification standard que tout autre code non standard = qui n'en est pas.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.