web-dev-qa-db-fra.com

Dois-je retourner un état HTTP 400 (demande incorrecte) si un paramètre est syntaxiquement correct, mais viole une règle métier?

Disons que j'ai un point de terminaison REST qui prend un entier comme paramètre:

/makeWaffles?numberOfWaffles=3

Dans ce cas, je veux que le nombre soit positif car je ne peux pas faire un nombre négatif de gaufres (et demander 0 gaufres est une perte de temps). Je veux donc rejeter toute demande qui ne contient pas d'entier positif. Je veux également rejeter une demande qui dépasse un nombre entier maximum (disons pour l'instant que c'est MAX_INTEGER).

Dans le cas où quelqu'un demande un nombre non positif de gaufres, dois-je retourner un état HTTP 400 (Bad Request)? Ma première pensée est oui: ce n'est pas un numéro valide pour moi de compléter la demande. Cependant, le RFC ne mentionne pas les règles métier comme raison de le jeter:

Le code d'état 400 (mauvaise demande) 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).

Une règle commerciale ne relève d'aucun de ces trois exemples. C'est syntaxiquement correct, il est correctement cadré et ce n'est pas un routage de demande trompeur.

Dois-je donc retourner un état HTTP 400 (Bad Request) si un paramètre est syntaxiquement correct, mais viole une règle métier? Ou existe-t-il un statut plus approprié pour revenir?

67
Thunderforge

C'est une grande question, et toujours 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 existe des définitions contradictoires. Cela peut être clarifié en se déplaçant chronologiquement.

RFC 2616 (juin 1999)

10.4.1 400 Mauvaise requête

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.

À partir de cette RFC, ce code d'état ne s'appliquait spécifiquement qu'aux requêtes syntaxiquement invalides. Il y avait une lacune dans les codes de statut 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é non traitable

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. 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 validation sémantique dans la spécification d'origine des codes d'état 4xx. Cependant, un autre RFC pertinent est apparu en 2014 qui a généralisé 400 pour ne plus être spécifique à la syntaxe .

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

6.5.1. 400 Mauvaise demande

Le code d'état 400 (mauvaise demande) 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).

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

Revenons à la question: bien que 422 soit techniquement plus spécifique, étant donné ce contexte, je pouvais voir 400 ou 422 utilisés pour la validation sémantique des paramètres API. J'hésite à utiliser le 422 dans mes propres API car la définition du 422 est techniquement dépassée à ce stade (bien que je ne sache pas si cela est officiellement reconnu quelque part). L'article référencé dans la réponse de Fran qui encourage l'utilisation du 422 a été écrit en 2012, deux ans avant que la RFC 7231 clarifie HTTP 400. Assurez-vous simplement de standardiser l'un ou l'autre.

54
Kyle McVay

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

de l'IETF

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

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

44
Fran

Non tu ne devrais pas. Les codes HTTP sont destinés à la couche HTTP de votre application. Les règles métier sont complètement différentes 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 devrez donc changer votre couche métier pour vous y adapter. Mais votre entreprise n'a pas vraiment changé, vous ne devriez donc pas avoir besoin de changer de couche métier. Il montre un couplage étroit entre ces deux couches (transport et entreprise).

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. La spécification le dit clairement:

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

200 OK

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

[~ # ~] poster [~ # ~] une entité décrivant ou contenant le résultat de l'action;

Votre requête HTTP a-t-elle réussi? Oui, le serveur Web sait quoi faire de 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 prend 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 "Génial, 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 c'est à votre client de faire une demande pour comprendre ce que signifie la réponse.

PS: "400 Bad Request" signifie que le serveur web n'a pas compris ce que vous en attendez. 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 signifie :-)

[~ # ~] edit [~ # ~] : Je viens de réaliser que vous faites une requête GET, pas POST. C'est une mauvaise idée car GET ne doit pas changer l'état de l'application. GET est censé simplement récupérer les données du serveur. Mais dans votre demande, vous modifiez réellement l'état de l'application, vous devriez donc vraiment utiliser POST.

11
GoFree

Oui, une entrée qui ne suit pas le contrat implicite du point de terminaison est "quelque chose perçu comme une erreur client" et devrait renvoyer 400.

Les exceptions à cette règle sont si la règle métier est liée à la sécurité (alors 401 Unauthorized ou 403 Forbidden serait mieux). Alternativement, si l'envoi d'un 400 entraînerait une fuite d'informations sur l'existence de quelque chose, puis un 404 Not Found peut être plus approprié.

8
Telastyn