Dois-je renvoyer un statut HTTP 400 (requête incorrecte) si un paramètre est syntaxiquement correct, mais enfreint une règle de gestion?

56

Dites que j'ai un point de terminaison REST qui prend un entier en tant que paramètre:

/makeWaffles?numberOfWaffles=3

Dans ce cas, je veux que le nombre soit positif car je ne peux pas créer un nombre négatif de gaufres (et demander 0 gaufres est une perte de temps). Je souhaite donc rejeter toute demande ne contenant pas d’entier positif. Je souhaite également rejeter une demande dépassant un nombre entier maximal (disons pour l'instant qu'il s'agit de MAX_INTEGER).

Si quelqu'un demande un nombre non positif de gaufres, dois-je renvoyer un statut HTTP 400 (Requête incorrecte)? Ma pensée initiale est oui: ce n'est pas un nombre valide pour compléter la demande. Cependant, le RFC ne mentionne pas les règles commerciales comme une raison de le jeter:

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

Une règle de gestion ne relève d'aucun de ces trois exemples. C'est syntaxiquement correct, c'est bien cadré, et ce n'est pas un routage de requête trompeur.

Devrais-je donc renvoyer un statut HTTP 400 (requête incorrecte) si un paramètre est syntaxiquement correct, mais enfreint une règle de gestion? Ou y a-t-il un statut plus approprié à renvoyer?

Thunderforge
la source

Réponses:

38

C'est une excellente question, qui reste très pertinente compte tenu du contexte historique (et des définitions apparemment contradictoires) des codes de retour HTTP. Même parmi les réponses à cette question, il y a des définitions contradictoires. Cela peut être clarifié en se déplaçant chronologiquement.

RFC 2616 (juin 1999)

10.4.1 400 mauvaise demande

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.

À partir de cette RFC, ce code d'état ne s'appliquait spécifiquement qu'aux requêtes syntaxiquement non valides. Il y avait une lacune dans les codes d'état pour la validation sémantique. Ainsi, lorsque la RFC 4918 est apparue, un nouveau code est né.

RFC 4918 (juin 2007)

11.2 422 entités non traitables

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. Par exemple, 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.

422 Entité non traitable a été créée pour combler le vide de la validation sémantique dans la spécification d'origine des codes d'état 4xx. Cependant, une autre RFC pertinente est apparue en 2014, généralisant 400 pour ne plus être spécifiques à la syntaxe .

RFC 7231 (juin 2014, obsolète explicitement le RFC 2616)

6.5.1. 400 mauvaise demande

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

Notez que la description 422 indique que la raison 400 n'est pas appropriée, car 400 (à partir de la RFC 2616) doit être renvoyé uniquement pour une syntaxe de requête incorrecte. Cependant, à partir de la RFC 7231, la définition d'erreur de syntaxe stricte ne s'applique plus à 400 .

Revenons à la question: Si 422 est techniquement plus spécifique, dans ce contexte, je pourrais voir que 400 ou 422 sont utilisés pour la validation sémantique des paramètres API. J'hésite à utiliser 422 dans mes propres API car la définition de 422 est techniquement obsolète pour le moment (bien que je ne sache pas si c'est officiellement reconnu nulle part). L'article référencé dans la réponse de Fran qui encourage l'utilisation de 422 a été écrit en 2012, deux ans avant que la RFC 7231 clarifie HTTP 400. Veillez simplement à uniformiser l'un ou l'autre.

Kyle McVay
la source
42

J'ai lu la première réponse et je ne suis pas vraiment d'accord avec elle car, du moins dans mon interprétation, une mauvaise demande (400) signifie: "Je ne peux même pas traiter votre demande car quelque chose qui ne va pas du tout au tout." Et j'ai trouvé ce post qui plaide en faveur du retour d'un 422.

de l'IETF

422 Entité non traitable (WebDAV; RFC 4918) La demande était bien formée mais ne pouvait pas être suivie en raison d'erreurs sémantiques

Cela semble être une réponse plus appropriée puisque votre demande est bien formée, mais ne respecte pas vos règles de validation.

Fran
la source
5
J'ai entendu dire que "400 signifie mauvaise syntaxe, 422 signifie mauvaise sémantique".
cbojar
33
Tous les codes x00 sont des codes génériques "attrapez tous". Un 400 n'est pas inapproprié , mais moins spécifique .
Jack
1
Bonne réponse, mais la réponse donnée par @GoFree est plus logique pour moi.
Ewerton
2
Les codes de retour sont connus pour tout le monde. Absolument tout le monde devra regarder 422, et je parie que la plupart ne sauront toujours pas quoi en faire.
Sylvanaar
9

Non tu ne devrais pas. Les codes HTTP sont destinés à la couche HTTP de votre application. Les règles commerciales constituent une couche complètement différente et sont spécifiques à l'application. Vous devez donc créer votre propre "protocole".

Imaginez qu’une apocalypse se produise et que vous deviez passer du protocole HTTP à l’utilisation de Pigeons. Les pigeons n’ont pas de code de retour, vous devez donc modifier votre couche métier pour vous adapter à cela. Mais votre entreprise n'a pas vraiment changé de quelque manière que ce soit, vous ne devriez donc pas avoir besoin de changer de couche métier. Il montre un couplage étroit entre ces deux couches (transport et affaires).

Retour à la question: Ce que vous devez faire est de retourner "200 OK" avec un corps décrivant ce qui s'est passé avec la demande. Le cahier des charges le dit clairement:

https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1 .

200 OK

La demande a réussi. Les informations renvoyées avec la réponse dépendent de la méthode utilisée dans la demande , par exemple

POST une entité décrivant ou contenant le résultat de l'action;

Votre demande HTTP a-t-elle abouti? Oui, le serveur Web sait quoi faire avec cette demande (par exemple, transmettez-la à la partie serveur de votre application). Le serveur Web transmet ensuite cette demande à la partie serveur de votre application, qui récupère les données POSTées, les traite (les valide dans votre cas) et renvoie une réponse normale (dans le corps d'une réponse HTTP) à la partie client de votre application. . Cette réponse de la partie serveur de l'application peut être "Excellent, les données que vous m'avez envoyées sont valides" ou "Je suis désolé, les données que vous avez envoyées ne sont pas valides". Et il appartient à votre partie cliente de l’application de comprendre la réponse.

PS: "400 Bad Request" signifie que le serveur Web n'a pas compris ce que vous souhaitiez. Cela signifie que la partie serveur de votre application n'a même pas reçu la demande. Ou du moins c'est ce que cela veut dire :-)

EDIT : Je viens de me rendre compte que vous faites la demande GET, pas POST. C'est une mauvaise idée car GET ne doit pas modifier l'état de l'application. GET est supposé récupérer simplement des données du serveur. Mais dans votre demande, vous changez réellement l'état de l'application, vous devriez donc vraiment utiliser POST.

Passez au gratuit
la source
1
Oui, retourner 404 dans ce cas est correct. Je ne dis pas que le serveur doit toujours envoyer 200 OK avec une explication dans le corps.
GoFree
Meilleure explication que j'ai vue jusqu'à présent. J'ai cette même question et semble que tout le mot pense différente de moi et vous @GoFree
Ewerton
@GoFree C'est une très bonne réponse pour repenser la conception des API. Mais n'est-il pas vrai que nous utilisons HTTP et son code de réponse comme partie intégrante de la couche de règles métier lorsque nous utilisons une API REST?
Thomas Lauria
1
@Thomas Lauria Je n'ai pas encore vu une implémentation appropriée de RESTFUL API. Cependant, l’API REST est un mot à la mode de nos jours et chaque entreprise doit donc l’utiliser (le mot, pas la technologie) sans comprendre le concept qui le sous-tend. Donc, oui, il est utilisé de manière fausse partout. Ce que les programmeurs créent habituellement n'est pas une API REST, mais une API HTTP ou une API SUR HTTP. L'une des rares bonnes implémentations de RESTFUL est le HTTP lui-même :)
GoFree
1
Utiliser 200-OK est particulièrement logique si l'application inclut un champ "erreur" dans le corps de la réponse pour décrire les erreurs de niveau métier telles que la valeur d'entrée trop élevée ou trop basse ou manquante, le produit en rupture de stock, etc.
Roland
8

Oui, les entrées qui ne suivent pas le contrat implicite du système d'extrémité sont "quelque chose qui est perçu comme une erreur du client" et doivent renvoyer 400.

Les exceptions à cela sont si la règle de gestion est liée à la sécurité (alors 401 Unauthorizedou 403 Forbiddenserait mieux). Alternativement, si envoyer un 400 fuirait des informations sur l'existence de quelque chose, alors un 404 Not Foundpeut être plus approprié.

Telastyn
la source
-3

Pas sûr que tous soient d'accord, mais nous utilisons 409 - Conflict. Beaucoup affirment que la 409 est davantage en conflit avec l’état du système, mais nous avons accepté l’interprétation voulant que le demandeur puisse corriger un conflit en ce qui concerne les valeurs de données, et une utilisation acceptable de la valeur 409. 422 Je pense que ce serait raisonnable, car la demande est correctement formé mais ne peut pas être traité comme demandé. Je pense toutefois que si vous ne souhaitez pas mettre en œuvre une foule de réponses, il est toujours acceptable de donner un 400.

dlb
la source
5
409 signifie "l'état dans lequel vous essayez de placer ceci est en conflit avec l'état qu'un autre client essaie de mettre ceci dans", c'est pour bloquer les écritures simultanées (en utilisant ETags, par exemple)
Jack