web-dev-qa-db-fra.com

REST Codes de statut HTTP pour échec de la validation ou duplication non valide

Je construis une application avec une API basée sur REST et suis arrivé au point où je spécifie des codes d'état pour chaque demande.

Quel code d'état dois-je envoyer pour les demandes dont la validation a échoué ou lorsqu'une demande tente d'ajouter un doublon dans ma base de données?

J'ai parcouru http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html mais aucun d'entre eux ne semble correct.

Existe-t-il une pratique courante lors de l'envoi de codes d'état?

761
alexn

En cas d'échec de la validation de l'entrée: 400 requêtes incorrectes + votre description facultative. Ceci est suggéré dans le livre " RESTful Web Services ". Pour double soumettre: 409 Conflict


Mise à jour juin 2014

La spécification pertinente était RFC2616 , ce qui donnait l’utilisation de 400 (requête incorrecte) plutôt étroitement

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

Donc pourrait avoir été argumenté que cela était inapproprié pour les erreurs sémantiques. Mais plus maintenant; depuis juin 2014, la norme pertinente RFC 7231 , qui remplace la précédente RFC2616, indique l'utilisation de 400 (Bad Request) plus largement

le serveur ne peut pas ou ne traitera pas la demande en raison d'une erreur perçue par le client

730
deamon
  • Échec de la validation: 403 Interdit ("Le serveur a compris la demande, mais refuse de l'exécuter"). Contrairement à l'opinion populaire, le RFC2616 ne dit pas "403 est uniquement destiné à l'authentification échouée", mais "403: je sais ce que vous voulez, mais je ne le ferai pas". Cette condition peut être ou ne pas être due à l'authentification.
  • Tentative d’ajout d’un doublon: 409 Conflict ("La demande n’a pas pu être complétée en raison d’un conflit avec l’état actuel de la ressource.")

Vous devez absolument donner une explication plus détaillée dans les en-têtes et/ou le corps de la réponse (par exemple, avec un en-tête personnalisé - X-Status-Reason: Validation failed).

270
Piskvor

Je recommande code d'état 422, "Entité non traitable" .

11.2 422 entités non traitables

Le code de statut 422 (entité non traitable) signifie que le serveur comprend le type de contenu de l'entité de demande (par conséquent, un code de statut 415 (type de support non pris en charge) est inapproprié), et la syntaxe de l'entité de demande est correcte (par conséquent, une requête de type 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 requête XML contient des instructions XML bien formées (c'est-à-dire syntaxiquement correctes), mais sémantiquement erronées.

192
Julian Reschke

200 300, 400, 500 sont tous très génériques. Si vous voulez générique, 400 est OK.

422 est utilisé par un nombre croissant d'API, et même par Rails prêt à l'emploi.

Quel que soit le code d'état que vous choisissez pour votre API, quelqu'un ne sera pas d'accord. Mais je préfère 422 parce que je pense que "400 + statut du texte" est trop générique. De plus, vous ne tirez pas parti d'un analyseur syntaxique compatible JSON; En revanche, un 422 avec une réponse JSON est très explicite, et une grande quantité d'informations d'erreur peut être transmise.

En parlant de réponse JSON, j’ai tendance à normaliser la réponse d’erreur Rails pour ce cas, qui est:

{
    "errors" :
    { 
        "arg1" : ["error msg 1", "error msg 2", ...]
        "arg2" : ["error msg 1", "error msg 2", ...]
    }
}

Ce format convient parfaitement à la validation de formulaire, que je considère comme le cas le plus complexe à prendre en charge en termes de "richesse de rapport d'erreur". Si votre structure d'erreur est la suivante, il gérera probablement tous vos besoins en matière de génération de rapports d'erreur.

76
sethcall

Un duplicata dans la base de données doit être un 409 CONFLICT.

Je recommande d'utiliser 422 UNPROCESSABLE ENTITY pour les erreurs de validation.

Je donne une explication plus longue des codes 4xx ici: http://parker0phil.com/2014/10/16/REST_http_4xx_status_codes_syntax_and_sematics/

38
Phil Parker

200

Ugh ... (309, 400, 403, 409, 415, 422) ... beaucoup de réponses essayant de deviner, argumenter et normaliser quel est le meilleur code retour pour une requête HTTP réussie mais un échec REST appel.

Il est incorrect de mélanger les codes d'état HTTP et les codes d'état REST.

Cependant, j'ai vu de nombreuses implémentations les mélanger et de nombreux développeurs pourraient ne pas être d'accord avec moi.

Les codes de retour HTTP sont liés au HTTP Request lui-même. Un appel REST est effectué à l'aide d'une demande Hypertext Transfer Protocol et fonctionne à un niveau inférieur à celui de la méthode invoquée REST. REST est un concept/une approche et son résultat est un résultat business/logical, alors que le code de résultat HTTP est un résultat transport.

Par exemple, renvoyer "404 non trouvé" lorsque vous appelez/utilisateurs/est confus, car cela peut vouloir dire:

  • L'URI est incorrect (HTTP)
  • Aucun utilisateur trouvé (REST)

"403 Interdit/Accès refusé" peut signifier:

  • Une autorisation spéciale est nécessaire. Les navigateurs peuvent le gérer en demandant à l'utilisateur/mot de passe. (HTTP)
  • Mauvaises autorisations d'accès configurées sur le serveur. (HTTP)
  • Vous devez être authentifié (REST)

Et la liste peut continuer avec une erreur "500 Server" (une erreur HTTP Apache/Nginx ou une erreur de contrainte commerciale dans REST) ​​ou d’autres erreurs HTTP, etc.

A partir du code, il est difficile de comprendre quelle était la raison de l'échec, une défaillance HTTP (transport) ou une défaillance REST (logique).

Si la requête HTTP a été correctement exécutée physiquement, elle doit toujours renvoyer le code 200, que les enregistrements soient ou non trouvés. Parce que la ressource URI est trouvée et a été gérée par le serveur HTTP. Oui, cela peut retourner un jeu vide. Est-il possible de recevoir une page Web vide avec 200 comme résultat HTTP, non?

Au lieu de cela, vous pouvez renvoyer 200 codes HTTP avec certaines options:

  • Objet "erreur" dans le résultat JSON en cas de problème
  • Tableau/objet JSON vide si aucun enregistrement n'a été trouvé
  • Un indicateur résultat/succès en combinaison avec les options précédentes pour une meilleure gestion.

De plus, certains fournisseurs d'accès à Internet peuvent intercepter vos demandes et vous renvoyer un code HTTP 404. Cela ne signifie pas que vos données ne sont pas trouvées, mais que quelque chose ne va pas au niveau du transport.

De Wiki :

En juillet 2004, le groupe de télécommunications britannique BT Group a déployé le système de blocage de contenu Cleanfeed, qui renvoie une erreur 404 à toute demande de contenu identifié comme potentiellement illégal par Internet Watch Foundation. D'autres fournisseurs de services Internet renvoient une erreur "interdite" HTTP 403 dans les mêmes circonstances. La pratique consistant à utiliser de fausses erreurs 404 comme moyen de dissimuler la censure a également été rapportée en Thaïlande et en Tunisie. En Tunisie, où la censure était sévère avant la révolution de 2011, les gens ont pris conscience de la nature des fausses erreurs 404 et ont créé un personnage imaginaire nommé "Ammar 404" qui représente "le censeur invisible".

Pourquoi ne pas simplement répondre avec quelque chose comme ça?

{
  "result": false,
  "error": {"code": 102, "message": "Validation failed: Wrong NAME."}
}

Google renvoie toujours 200 en tant que code d'état dans leur API de géocodage, même si la demande échoue logiquement: https://developers.google.com/maps/documentation/geocoding/intro#StatusCodes

Facebook renvoie toujours 200 pour les demandes HTTP réussies, même si la demande REST échoue: https://developers.facebook.com/docs/graph-api/using-graph-api/error-handling

C'est simple, les codes d'état HTTP sont pour les requêtes HTTP. REST L'API est Votre, définissez Vos codes d'état.

26
Marcodor

L'adaptateur ActiveRecord d'Ember-Data s'attend à ce que 422 UNPROCESSABLE ENTITY soit renvoyé du serveur. Donc, si votre client est écrit dans Ember.js, vous devriez utiliser 422. Seulement alors, DS.Errors sera rempli avec les erreurs retournées. Vous pouvez bien sûr changer le code 422 en un autre code dans votre adaptateur.

7
Daniel Kmak

Code de statut 304 non modifié fournirait également une réponse acceptable à une demande dupliquée. Ceci est similaire au traitement d'un en-tête de If-None-Match à l'aide d'une balise d'entité.

À mon avis, la réponse de @ Piskvor est le choix le plus évident pour ce que je perçois comme étant l'intention de la question initiale, mais j'ai une solution de rechange tout aussi pertinente.

Si vous souhaitez traiter une demande dupliquée comme un avertissement ou une notification plutôt que comme une erreur, un code d'état de réponse de 304 Not Modified et de l'en-tête Content-Location identifiant la ressource existante serait tout aussi valide. Lorsque l'intention est simplement de s'assurer de l'existence d'une ressource, une demande en double ne serait pas une erreur, mais une confirmation. La demande n'est pas erronée, mais simplement redondante et le client peut faire référence à la ressource existante.

En d'autres termes, la demande est bonne, mais comme la ressource existe déjà, le serveur n'a pas besoin d'effectuer de traitement supplémentaire.

6
Suncat2000