L'erreur de l'API REST renvoie les bonnes pratiques [fermé]

623

Je recherche des conseils sur les bonnes pratiques en matière de retour d'erreurs à partir d'une API REST. Je travaille sur une nouvelle API afin que je puisse prendre n'importe quelle direction dès maintenant. Mon type de contenu est XML pour le moment, mais je prévois de prendre en charge JSON à l'avenir.

J'ajoute maintenant quelques cas d'erreur, comme par exemple un client tente d'ajouter une nouvelle ressource mais a dépassé son quota de stockage. Je gère déjà certains cas d'erreur avec des codes de statut HTTP (401 pour l'authentification, 403 pour l'autorisation et 404 pour les URI de demande non valides). J'ai regardé les codes d'erreur HTTP bénis, mais aucun de la plage 400-417 ne semble correct de signaler des erreurs spécifiques à l'application. Donc, au début, j'ai été tenté de renvoyer mon erreur d'application avec 200 OK et une charge utile XML spécifique (c'est-à-dire. Payez-nous plus et vous obtiendrez le stockage dont vous avez besoin!) Mais je me suis arrêté pour y penser et cela semble savonneux (/ hausser les épaules avec horreur). De plus, j'ai l'impression de diviser les réponses d'erreur en cas distincts, car certains sont basés sur le code de statut http et d'autres sur le contenu.

Alors, quelles sont les recommandations de l'industrie? Bonnes pratiques (expliquez pourquoi!) Et aussi, à partir d'un point de vue client, quel type de gestion des erreurs dans l'API REST facilite la vie du code client?

Remus Rusanu
la source
7
Juste pour clarifier: je ne suis pas tellement intéressé par le code d'état HTTP particulier à renvoyer, mais s'il est une bonne pratique REST de combiner les erreurs de charge utile avec les codes d'état HTTP ou s'il vaut mieux s'appuyer uniquement sur la charge utile.
Remus Rusanu
3
Le manuel de conception de l'API REST couvre assez bien ce sujet.
Remus Rusanu
12
La question ne demande pas d'avis, mais des orientations / recommandations et doit être rouverte et utilisée comme référence. Quel était le point de fermer en 2016 la question, qui a été créée en 2009, a plus de 400 votes et aucune des réponses existantes basées sur des opinions
Michael Freidgeim
4
La plupart n'ont pas mentionné, mais l'utilisation des codes d'erreur HTTP peut entraîner des problèmes concernant la cause principale d'un problème. HTTP est le protocole de transport et un 404 devrait indiquer qu'il y avait un problème avec le niveau de transport URLon (par exemple un mauvais chemin). Si l'application ne peut pas trouver un ensemble de données par son identifiant, il s'agit d'une erreur au niveau de l'application (pas une erreur de niveau de transport) et un 404, comme suggéré par les utilisateurs de code d'état http reposant, peut conduire à une conclusion erronée. En général, je n'aime pas le mélange de transport et de couche d'application dans l'utilisation des codes d'état.
SCI

Réponses:

220

Donc, au début, j'ai été tenté de renvoyer mon erreur d'application avec 200 OK et une charge utile XML spécifique (c'est-à-dire. Payez-nous plus et vous obtiendrez le stockage dont vous avez besoin!) Mais je me suis arrêté pour y penser et cela semble savonneux (/ hausser les épaules avec horreur).

Je ne retournerais pas 200 sauf s'il n'y avait vraiment rien de mal à la demande. De RFC2616 , 200 signifie "la demande a réussi."

Si le quota de stockage du client a été dépassé (pour une raison quelconque), je retournerais un 403 (interdit):

Le serveur a compris la demande, mais refuse de la satisfaire. L'autorisation n'aidera pas et la demande NE DEVRAIT PAS être répétée. Si la méthode de demande n'était pas HEAD et que le serveur souhaite rendre public pourquoi la demande n'a pas été satisfaite, il DEVRAIT décrire la raison du refus dans l'entité. Si le serveur ne souhaite pas mettre ces informations à la disposition du client, le code d'état 404 (Not Found) peut être utilisé à la place.

Cela indique au client que la demande était OK, mais qu'elle a échoué (quelque chose qu'un 200 ne fait pas). Cela vous donne également la possibilité d'expliquer le problème (et sa solution) dans le corps de réponse.

Quelles autres conditions d'erreur spécifiques aviez-vous en tête?

Rich Apodaca
la source
6
Dois-je inclure mon message d'erreur détaillé dans le corps, c'est-à-dire. une paire code / chaîne XML? Comment les clients gèrent-ils le mieux cette situation? Par exemple, je sais que les clients basés sur C # WebRequest lanceraient «Bad Request» ou «Forbidden» et ne donneraient pas le corps de la réponse.
Remus Rusanu
18
Le corps d'un 403 "devrait" contenir les détails de l'erreur. Que le client soit prêt à utiliser les informations est une autre histoire. Il est plus logique que ce format soit le même que celui de toutes les autres charges utiles (par exemple, XML, JSON).
Rich Apodaca le
1
... et si les détails ne sont pas retournés dans le 403, un 404 "peut" être utilisé à la place (ne semble pas être la meilleure option pour moi, cependant).
Rich Apodaca
6
L'option 404 est pour le cas où un 403 pourrait révéler des détails sur l'application que vous ne voulez pas que les utilisateurs non autorisés connaissent - si un utilisateur non administratif frappe une URL réservée aux administrateurs, par exemple, vous ne voudrez peut-être pas que cet utilisateur savoir que c'est une URL valide pour les administrateurs, etc. Dans ce cas, cependant, le 403 est tout à fait approprié.
Greg Campbell
16
Je pense que c'est une réponse assez inutile. J'aurais pensé que l'aspect le plus important est de savoir si les statuts doivent être utilisés uniquement, ou si les informations d'erreur doivent être retournées dans la charge utile, ou les deux, etc. Et puis COMMENT les informations doivent être ajoutées dans la charge utile. Le statut spécifique qui est utilisé se concentre sur un seul aspect spécifique de la question.
Manachi
584

Une excellente ressource pour choisir le code d'erreur HTTP correct pour votre API: http://www.codetinkerer.com/2015/12/04/choosing-an-http-status-code.html

Un extrait de l'article:

Où commencer:

entrez la description de l'image ici

2XX / 3XX:

entrez la description de l'image ici

4XX:

entrez la description de l'image ici

5XX:

entrez la description de l'image ici

Omar Ali
la source
1
422 Est spécifiquement une extension WebDAV. Je pense que cela ne devrait pas être ici.
Mario
@Mario Il est idiomatique dans les API Ruby on Rails de renvoyer 422 en réponse aux conditions spécifiées ici. Beaucoup de bien suivant déjà cette approche. Pour quoi remplacer les utilisations du 422?
Kelsey Hannan
regular old 400
Andbdrew
Je vous remercie. Qu'est-ce que cela veut dire "Vous arrêtez de rage sur Internet?"?
RoutesMaps.com
@ Crimean.us google.com/search?q=define+rage-quit
Omar Ali
87

Le choix principal est si vous souhaitez traiter le code d'état HTTP comme faisant partie de votre API REST ou non.

Les deux méthodes fonctionnent bien. Je suis d'accord que, strictement parlant, l'une des idées de REST est que vous devez utiliser le code d'état HTTP dans le cadre de votre API (renvoyer 200 ou 201 pour une opération réussie et un 4xx ou 5xx selon divers cas d'erreur.) Cependant , il n'y a pas de police REST. Tu peux faire ce que tu veux. J'ai vu des API non REST beaucoup plus flagrantes être appelées «RESTful».

À ce stade (août 2015), je vous recommande d'utiliser le code d'état HTTP dans le cadre de votre API. Il est maintenant beaucoup plus facile de voir le code de retour lors de l'utilisation de frameworks que par le passé. En particulier, il est maintenant plus facile de voir le cas de retour non-200 et le corps des réponses non-200 que par le passé.

Le code d'état HTTP fait partie de votre API

  1. Vous devrez choisir soigneusement les codes 4xx qui correspondent à vos conditions d'erreur. Vous pouvez inclure un message de repos, xml ou texte en clair comme charge utile qui comprend un sous-code et un commentaire descriptif.

  2. Les clients devront utiliser une infrastructure logicielle qui leur permettra d'obtenir le code d'état au niveau HTTP. Habituellement faisable, pas toujours simple.

  3. Les clients devront faire la distinction entre les codes d'état HTTP qui indiquent une erreur de communication et vos propres codes d'état qui indiquent un problème au niveau de l'application.

Le code d'état HTTP ne fait PAS partie de votre API

  1. Le code d'état HTTP sera toujours 200 si votre application a reçu la demande et a ensuite répondu (cas de réussite et d'erreur)

  2. TOUTES vos réponses doivent inclure des informations «enveloppe» ou «en-tête». Généralement, quelque chose comme:

    enveloppe_ver: 1.0
    status: # utilisez les codes que vous aimez. Réservez un code pour réussir.
    msg: "ok" # Une chaîne humaine qui reflète le code. Utile pour le débogage.
    data: ... # Les données de la réponse, le cas échéant.
  3. Cette méthode peut être plus simple pour les clients car le statut de la réponse est toujours au même endroit (aucun sous-code nécessaire), aucune limite sur les codes, pas besoin de récupérer le code de statut au niveau HTTP.

Voici un article avec une idée similaire: http://yuiblog.com/blog/2008/10/15/datatable-260-part-one/

Problèmes principaux:

  1. Assurez-vous d'inclure les numéros de version afin de pouvoir modifier ultérieurement la sémantique de l'API si nécessaire.

  2. Document...

Larry K
la source
8
Ty. L'option 2 semble être du savon dans des vêtements de repos ...
Remus Rusanu
138
Non, tout tunneler à travers un 200 n'est pas du tout reposant. Il empêche les intermédiaires de comprendre le résultat d'une opération, ce qui tuera toute forme de mise en cache, il masque la sémantique de l'opération et il impose de comprendre le contenu du message pour traiter une erreur, violant ainsi la contrainte des messages autonomes.
SerialSeb
13
Renvoyer les détails de l'erreur avec un 200 peut ne pas être RESTful, mais c'est néanmoins une réponse utile (si vous ignorez la remarque "Les deux façons sont reposantes") ... Le plus grand point peut être qu'une API RESTful n'est peut-être pas la meilleure option pour l'OP.
MB.
3
Il semble y avoir une compréhension générale que vous pouvez faire ce que vous voulez avec le protocole HTTP et toujours être "RESTy", c'est faux. Utilisez le protocole pour ce qu'il est écrit, c'est l'une des idées fondamentales de REST. Le code d'état doit donc faire partie de votre protocole.
Ariel M.
Le but des codes d'état est de fournir un langage commun de compréhension entre divers langages de programmation, cadres et approches. Les significations des codes d'état sont presque universelles: votre corps personnalisé - qui ajoute intrinsèquement plus de complexité via la syntaxe personnalisée que vos clients API doivent apprendre - ne l'est pas.
Kelsey Hannan
40

N'oubliez pas qu'il y a plus de codes d'état que ceux définis dans les RFC HTTP / 1.1, le registre IANA se trouve à http://www.iana.org/assignments/http-status-codes . Dans le cas où vous avez mentionné le code d'état 507, cela semble juste.

Julian Reschke
la source
3
Hmm, même si en un coup d'œil "507 Insufficient Storage" semble être approprié, je me méfierais de l'utiliser, car il est conçu comme une extension WebDAV (assez spécifique) et non comme un "vous êtes à court d'espace" exception. Pourtant, je suppose que vous pourriez l'utiliser.
Max
1
Non, ce n'est pas du tout spécifique à WebDAV. Il y a une raison pour laquelle il existe un registre pour les codes d'état HTTP.
Julian Reschke
26
Je ne suis pas d'accord avec 507cet objectif. Mon interprétation 507est que le serveur est à court d'espace, pas que le compte est à court d'espace.
Patrick
12
Je suis d'accord avec Patrick. 5xxles erreurs concernent les erreurs liées au serveur.
Sean
10
418: "Je suis une théière", ce qui implique que l'espace de stockage est trop petit (comme une théière est petit) plutôt que grand et donc hors de l'espace.
Steve Konves
22

Comme d'autres l'ont souligné, il est parfaitement permis d'avoir une entité de réponse dans un code d'erreur.

N'oubliez pas que les erreurs 5xx sont côté serveur, c'est-à-dire que le client ne peut rien changer à sa demande pour que la demande soit acceptée. Si le quota du client est dépassé, ce n'est définitivement pas une erreur de serveur, donc 5xx doit être évité.

SerialSeb
la source
Je ne serais pas d'accord. Le quota dépassé serait une erreur de serveur (5xx) car: La demande du client est valide et aurait réussi si elle était sous quota, ce qui exclut la série 400.
mikek3332002
4
Mais le serveur n'a rien fait de mal.
Charlie Schliesser
19

Il existe deux sortes d'erreurs. Erreurs d'application et erreurs HTTP. Les erreurs HTTP sont juste pour faire savoir à votre gestionnaire AJAX que les choses se sont bien passées et ne doivent pas être utilisées pour autre chose.

5xx erreur du serveur

500 Internal Server Error
501 Not Implemented
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
505 HTTP Version Not Supported
506 Variant Also Negotiates (RFC 2295 )
507 Insufficient Storage (WebDAV) (RFC 4918 )
509 Bandwidth Limit Exceeded (Apache bw/limited extension)
510 Not Extended (RFC 2774 )

Succès 2xx

200 OK
201 Created
202 Accepted
203 Non-Authoritative Information (since HTTP/1.1)
204 No Content
205 Reset Content
206 Partial Content
207 Multi-Status (WebDAV)

Cependant, la façon dont vous concevez vos erreurs d'application dépend vraiment de vous. Stack Overflow par exemple envoie un objet response, dataet les messagepropriétés. Je crois que la réponse contient trueou falseindique si l'opération a réussi (généralement pour les opérations d'écriture). Les données contiennent la charge utile (généralement pour les opérations de lecture) et le message contient des métadonnées supplémentaires ou des messages utiles (tels que des messages d'erreur lorsqu'ils le responsesont false).

aleemb
la source
2
400 est également utile pour indiquer un problème dans l'application cliente.
dolmen
19

Je sais que c'est très tard pour la fête, mais maintenant, en 2013, nous avons quelques types de médias pour couvrir le traitement des erreurs de manière distribuée (RESTful). Voir "vnd.error", application / vnd.error + json ( https://github.com/blongden/vnd.error ) et "Détails du problème pour les API HTTP", application / problem + json ( https: // tools. ietf.org/html/draft-nottingham-http-problem-05 ).

Jørn Wildt
la source
2
Merci pour les liens. draft-nottingham-http-problem est maintenant une norme proposée: datatracker.ietf.org/doc/rfc7807
seanf
9

D'accord. La philosophie de base de REST est d'utiliser l'infrastructure Web. Les codes d'état HTTP sont le cadre de messagerie qui permet aux parties de communiquer entre elles sans augmenter la charge utile HTTP. Ce sont des codes universels déjà établis transmettant l'état de réponse, et donc, pour être vraiment RESTful, les applications doivent utiliser ce cadre pour communiquer l'état de réponse.

L'envoi d'une réponse d'erreur dans une enveloppe HTTP 200 est trompeur et oblige le client (consommateur api) à analyser le message, très probablement d'une manière non standard ou propriétaire. Ce n'est pas non plus efficace - vous obligerez vos clients à analyser la charge utile HTTP à chaque fois pour comprendre le statut de réponse «réel». Cela augmente le traitement, ajoute de la latence et crée un environnement permettant au client de faire des erreurs.

Kingz
la source
3
Que vous ayez une réponse réussie ou une réponse d'échec, vous allez très probablement analyser la réponse. S'il s'agit d'une erreur, vous souhaitez l'analyser pour faire sortir le message d'erreur. Les réponses d'erreur sont généralement petites et rapides à analyser. Je ne pense pas que nous devrions nous préoccuper d'essayer d'optimiser pour éviter d'analyser les réponses d'erreur. Souhaitez-vous simplement jeter la réponse d'erreur sans l'analyser? Imprudent à mon avis.
AgilePro
3
Si vous obtenez un 200 OK, vous pouvez également choisir de ne pas l'analyser, selon les règles de votre entreprise. La question n'est pas de savoir si nous l'analysons en tout temps ou non. Le point est l'intention - quelle est l'intention de 200 OK? Vous endommagez l'intention en envoyant des messages d'erreur enveloppés dans 200 OK.
Kingz
1
"quelle est l'intention de 200 OK?" - indiquant le succès de la couche transport. La demande a été reçue avec succès et a répondu, il y avait juste un problème spécifique à l'application n'ayant rien à voir avec HTTP. +++ Autrement dit: l'envoi de 404 dans le monde REST signifie que quelque chose n'a pas été trouvé, peut-être que l'URL est tout simplement incorrecte ou que la ressource à traiter ou quoi que ce soit d'autre n'a pas été trouvée. Sans analyser le message, vous ne pouvez pas. IMHO REST ne fait que fusionner des couches.
maaartinus
La confusion est la norme. Il vous fournit une syntaxe à gérer qui convient à votre raisonnement et vous permet de vous concentrer sur la couche métier. Convenu sur les communications de statut de transport ultérieur - c'est ce que l'objectif était en premier lieu - REST n'a pas été inventé / proposé simultanément avec HTTP - il est venu plus tard et a simplement décidé d'utiliser l'infrastructure existante pour représenter les ÉTATS et leurs CHANGEMENTS.
Kingz
5

Veuillez vous en tenir à la sémantique du protocole. Utilisez 2xx pour les réponses réussies et 4xx, 5xx pour les réponses d'erreur - que ce soit vos exceptions commerciales ou autres. Si l'utilisation de 2xx pour n'importe quelle réponse avait été le cas d'utilisation prévu dans le protocole, ils n'auraient pas d'autres codes d'état en premier lieu.

rahil008
la source
3

N'oubliez pas non plus les erreurs 5xx pour les erreurs d'application.

Dans ce cas, qu'en est-il du 409 (conflit)? Cela suppose que l'utilisateur peut résoudre le problème en supprimant les ressources stockées.

Sinon, le 507 (pas entièrement standard) peut également fonctionner. Je n'utiliserais pas 200 à moins que vous n'utilisiez 200 pour les erreurs en général.

Kathy Van Stone
la source
-2

Si le quota client est dépassé, c'est une erreur de serveur, évitez 5xx dans ce cas.

rente fixe
la source
3
Pourquoi éviter les erreurs de la série 5xx quand elles concernent des erreurs de serveur?
mikek3332002
7
'quota client dépassé' n'est pas une erreur de serveur à mon humble avis, c'est une restriction client et doit être inférieur à 4xx.
MyGGaN