Je travaille avec une API REST qui réside sur un serveur qui gère les données pour une multitude de périphériques IoT.
Ma tâche consiste à interroger le serveur à l'aide de l'API pour collecter des informations de performances spécifiques concernant ces périphériques.
Dans un cas, j'obtiens une liste des périphériques disponibles et leurs identifiants correspondants, puis interroge le serveur pour plus de détails à l'aide de ces identifiants (GUID).
Le serveur renvoie un 500 Internal Server Error
pour une requête sur l'un de ces ID. Dans mon application, une exception est levée et je ne vois pas les détails de l'erreur. Si j'examine la réponse de plus près avec Postman , je peux voir que le serveur a renvoyé JSON dans le corps qui contient:
errorMessage: "This ID does not exist"
.
Ne tenez pas compte du fait que le serveur a d'abord fourni l'ID - il s'agit d'un problème distinct pour le développeur.
Une API REST doit-elle renvoyer a 500 Internal Server Error
pour signaler qu'une requête fait référence à un objet qui n'existe pas? À mon avis, les codes de réponse HTTP doivent faire référence strictement au statut de l'appel REST, plutôt qu'aux mécanismes internes de l'API. Je m'attendrais à un 200 OK
avec la réponse contenant l'erreur et la description, qui serait la propriété de l'API en question.
Il me semble qu’il existe une différence potentielle dans les attentes en fonction de la structure de l’appel REST.
Considérez ces exemples:
http://example.com/restapi/deviceinfo?id=123
http://example.com/restapi/device/123/info
Dans le premier cas, l'ID de périphérique est transmis en tant que variable GET. Un 404 ou un 500 indiquerait que le chemin ( /restapi/deviceinfo
) est introuvable ou a entraîné une erreur de serveur.
Dans le second cas, l'ID de périphérique fait partie de l'URL. Je comprendrais mieux un 404 Not Found
, mais je pourrais quand même argumenter en fonction des parties du chemin qui sont interprétées comme des variables par rapport aux points d'extrémité.
Réponses:
Je pense qu'une réponse 404 est la meilleure correspondance sémantique ici, car la ressource que vous tentiez de trouver (telle que représentée par l'URI utilisé pour la requête) n'a pas été trouvée. Renvoyer une charge d'erreur dans le corps est raisonnable, mais pas obligatoire.
Selon la RFC 2616 , la définition du code d'état 404 est la suivante:
la source
/questions
, c'est/questions/368213
. Ce point final n'existe pas dans votre scénario. Pensez-y de cette façon: si vous faites un GET sur / foo / bar et qu'il n'y a pas de barre, pourquoi la réponse devrait-elle être différente si / foo existe ou non?How do you differentiate between a 404 meaning "the query returned no results" and a 404 meaning "the endpoint does not exist"?
- 400 Bad Request.Je vais utiliser vos exemples.
Si le noeud final renvoie un tableau JSON , le meilleur choix est
200 OK
d'utiliser un tableau vide si aucun résultat n'a été trouvé.Si le critère d' évaluation est conçu pour renvoyer un seul résultat , mon choix serait
404 NOT FOUND
, parce que, pour moi, la bonne syntaxe pour ce type de point final est:http://example.com/restapi/deviceinfo/123
. J'utilise généralement request param uniquement pour le filtrage et lorsque mon noeud final renvoie un tableau.Je pense que cette question a déjà été répondu ici . POST ou GET, le meilleur choix semble être
404 NOT FOUND
parce que la ressource123
n’a pas été trouvée.Dans les deux cas, je ne vois pas la nécessité d'expliquer pourquoi la demande n'a pas été complétée. Les informations de requête et le code HTTP expliquent déjà pourquoi.
la source
/itms/1234
ou/items/12234
.HTTP 404
est correct, car le serveur comprend la ressource demandée par le client, mais ne dispose pas de cette ressource.Le fait que vous travailliez avec une "API REST" est la clé. L’API doit se comporter comme si elle effectuait un transfert d’état représentatif, et non une fonction. (Bien sûr, le terme "REST" a pris un sens plus large, mais vous pouvez toujours utiliser ici son sens littéral.) Le client a demandé l’état de la ressource décrite par l’URL
http://example.com/restapi/device/123/info
. Une chaîne de requête (/deviceinfo?id=123
) ne changerait pas la situation. Le serveur sait que vous demandez le transfert de l'état du périphérique 123, mais il ne le reconnaît pas comme une ressource connue. DoncHTTP 404
.Les autres réponses possibles discutées ici ont aussi des significations spécifiques:
HTTP 200
- Nous avons l'état pour vous. c'est dans le corps de la réponse.HTTP 204
- Nous avons l'état pour vous. c'est vide.HTTP 400
- Nous ne pouvons pas dire de quelle ressource vous parlez. Fixez votre URL.HTTP 500
- Nous avons mal fonctionné. Pas ta faute.Voir RFC 2616 Sec. 10 selon le cas.
la source
Une erreur 5xx est généralement utilisée pour indiquer que le serveur a rencontré une erreur et ne peut pas terminer la demande. Si le serveur accepte la demande, peut l'analyser avec succès et fait ensuite son travail, cela ne devrait pas renvoyer d'erreur 5xx.
Je ne sais pas s'il existe une quelconque convention sur ce qu'il faut retourner si une requête ne donne aucun résultat. J'ai vu à la fois ce que vous décrivez (un 200 avec un corps contenant un message) et un 404 indiquant que les résultats n'ont pas été trouvés. Le 200 est probablement le plus logique - la demande a abouti et il n'y a eu aucun problème avec la demande du client ou pendant le traitement de la demande par le serveur. Un corps peut transmettre un message au client.
Je traiterais vos deux exemples (
http://example.com/restapi/deviceinfo?id=123
ethttp://example.com/restapi/device/123/info
) de la même façon,123
c’est un paramètre. Les deux cas sont des manières différentes de structurer une demande pour obtenir les informations de périphérique pour un périphérique avec l'ID 123.Premièrement, je considérerais l'autorisation et l'authentification. Si l'utilisateur ne dispose pas des autorisations appropriées, je renverrais un 403 ou un 401 selon le cas. Bien que cela s'appelle "Unauthorized", je crois comprendre que 401 concerne davantage l'authentification et 403, une autorisation non autorisée ou une autorisation refusée. Je ne serais cependant pas trop pointilleux ici, si vous vouliez simplement vous en tenir à 403 pour toutes les erreurs d'authentification et d'autorisation.
Ensuite, je gérerais l'ID. D'après votre exemple, cela ressemble à un identifiant numérique. Si une valeur non numérique était fournie, je renverrais un 400. Si le paramètre pouvait éventuellement être un identifiant de périphérique valide, je poursuivrais le traitement. S'il y avait d'autres arguments, ils seraient également vérifiés ici. Je m'attendrais à ce que le corps de la réponse contienne les informations appropriées sur les raisons pour lesquelles la demande était incorrecte.
Si tous les paramètres étaient valides, je commencerais à traiter la demande. Si le système ou une dépendance quelconque (base de données, service tiers, autre service interne) n'est pas disponible, je renverrais un code 5xx - 503 serait spécifique, mais un code 500 serait également acceptable. Dans les deux cas, je retournerais un corps avec des détails supplémentaires. Ne considérez pas que si une dépendance externe signale un délai d'expiration de la demande 408, je la consommerais et renverrais 500 à mon client, ce qui permettrait à un client de recevoir un 408 uniquement si la demande de mon système expirait. Si le système est en mesure de compléter la demande, je renverrais un 200 et l'organisme approprié.
204 peut être utile dans certains cas, mais cela vous empêche d'envoyer un corps de réponse. En particulier dans un paramètre d'API, envoyer un corps de réponse avec des informations pouvant être introduites dans un mécanisme de journalisation ou de rapport semble être la bonne décision à prendre dans la plupart des cas.
Si un serveur 404 est renvoyé, c'est uniquement si le serveur ne dispose pas d'un
/deviceinfo
terminal ou d'un/device/:id/info
terminal.Je ne considérerais pas qu'un identifiant qui ne soit pas identique à la ressource non trouvée. La ressource est l'information sur le périphérique pour un périphérique particulier (dans votre exemple). Le renvoi d'un 404 signifierait que la ressource (les informations sur le périphérique) n'existe pas. Un 200 avec un corps approprié signifie que le système peut en effet fournir des informations sur le périphérique. Il peut y avoir ou non un périphérique avec l'ID spécifié.
la source
device: 123; status: not found;
. Ensuite, je sais que la requête a fonctionné et que l’API me fournit des informations utiles.Une erreur HTTP de série 500 indique un dysfonctionnement du serveur. Mis à part
501 Not Implemented
et505 HTTP Version Not Supported
, l'utilisation de ces codes d'erreur implique que la nouvelle tentative ultérieure de la demande peut aboutir (bien que503 Service Unavailable
ne l'indique explicitement que cela). Dans l’idéal, un serveur ne devrait jamais produire l’un de ces codes, mais son incapacité à écrire un logiciel exempt de bogues et à le doter de ressources infinies signifie que vous en aurez besoin de temps à autre.Pour un résultat "objet inexistant", vous devez probablement renvoyer soit
404 Not Found
(lorsque la demande concerne un objet par nom), soit200 Success
avec un corps de résultat vide (lors de la recherche d'objet par attributs).204 No Content
Cela semble tentant, mais je l’utiliserais seulement dans les situations où l’absence d’un corps de réponse est le résultat attendu.la source
En tant que client de votre API, lorsque je passe l'un de ces appels:
http://example.com/restapi/deviceinfo?id=123
http://example.com/restapi/device/123/info
Je m'attends à récupérer une (représentation) d'un
DeviceInfo
objet (ou un type particulier, de toute façon, qu'il s'agisse d'un type formel ou simplement conforme à une convention documentée "type de canard"). Je veux un200
statut qui signifie que j'en ai un, et que je peux l'utiliser et l'utiliser.Pour les API REST, je considère les codes d’état 400 et 500 comme des exceptions. Vous les utilisez pour indiquer lorsque vous ne pouvez pas renvoyer une réponse "normale" à la demande que vous avez reçue. Le client devra donc faire quelque chose d'exceptionnel plutôt que de traiter les informations qu'il s'attendait à récupérer.
Cela signifie, en tant que consommateur d’API, que je peux utiliser une sorte de fonction d’appel vérifié-en attente qui extrait une réponse ou lève une exception. C'est génial; ma logique normale peut être un code en ligne droite, et je peux organiser ma gestion des erreurs de la même manière que dans le code local. Les 404 inattendus se manifesteront sous forme d'exceptions "aucune ressource trouvée" sans que je doive faire quoi que ce soit, et non sous forme d'erreur "d'attribut manquant" lorsque je traiterai ultérieurement
{ errorMessage: "Device 123 not found" }
comme s'il s'agissait d'unDeviceInfo
objet.Si vous estimez que le noeud final
http://example.com/restapi/deviceinfo
est trouvé et que seul le résultatid=123
n'est pas trouvé et que 200 est renvoyé avec un message d'erreur dans le corps, vous créez exactement le même type de problèmes d'interface que les fonctions C qui pourraient renvoyer un résultat correct ou un code d'erreur, ou des méthodes qui indiquent des problèmes en renvoyant arbitrairementnull
. Il est beaucoup plus agréable, en tant qu'utilisateur de votre interface, de signaler les erreurs via un canal "distinct" des retours normaux. Cela s'applique ici aussi, même si les réponses HTTP 200, 404 et 500 sont le même canal du point de vue de bas niveau. Ils sont standardisés et faciles à distinguer afin que mon framework client REST puisse facilement activer ces statuts pour les transformer en structures appropriées dans ma langue; pour faire la même chose avec la couche JSON (où vous dites toujours 200 et donnez-moi unDeviceInfo
message d'erreur ou un message d'erreur), je dois intégrer certaines connaissances des schémas JSON que vous utilisez.Vous ne devez donc utiliser 200 que lorsque vous pouvez renvoyer une valeur valide du type attendu (raison pour laquelle vous
http://example.com/restapi/search-devices?colour=blue
pouvez en renvoyer 200 avec un tableau vide s'il n'y a pas de périphériques bleus; un tableau vide est un tableau valide et une réponse pertinente à la demande "I voudrait les détails de tous les appareils bleus "). Si vous ne pouvez pas, utilisez le code de statut non-200 le plus approprié. Même si "le périphérique 123 n'existe pas" est la réponse correcte à "donnez-moi les détails du périphérique 123" et ne constitue pas une erreur pour le serveur , il constitue une exception pour le client dans l'espoir qu'il récupéreraDeviceInfo
et devrait ne pas être communiquée comme une réponse normale "voici ce que vous avez demandé".la source
Vous pouvez utiliser l'erreur 422 Entité non traitable pour différencier de 404 non trouvé . 422 signifie que le serveur comprend la demande mais ne peut pas donner une réponse correcte. J'utilise ce code dans des situations similaires.
la source
L'erreur 500 indique normalement que la demande a bloqué un programme côté serveur; dans les environnements d'entreprise, ces erreurs sont traitées comme un œuf au visage et sont évitées.
Une erreur 4xx doit signaler au programmeur que le point de terminaison de l'API (ressource) n'existe pas. Par conséquent, une fois que le point de terminaison approprié est atteint, toute gestion d'erreur à partir de ce moment est la responsabilité du programmeur de l'API, qui doit être gérée correctement, c'est-à-dire avec un message d'erreur d'une réponse de 200.
la source
Bien que le w3 note que 404 est utilisé lorsqu'aucune autre réponse n'est applicable , ne serait-ce pas ce pour quoi une réponse 204 (sans contenu) est bonne? La demande était valide du point de vue du traitement et le serveur a traité la demande et a obtenu un résultat. C'est un succès, qui penche vers des réponses 2xx. Il n'y avait pas de contenu pour cette requête particulière, donc 204 indique à l'utilisateur qu'il n'y a rien d'anormal à leur requête mais qu'il n'y a rien.
Vous pouvez également faire valoir que 409 (Conflict) est une réponse appropriée. Bien que 409 soit le plus souvent utilisé pour un POST, il est dit
on peut soutenir que la non-existence de l'identifiant demandé est le conflit ici, et le fait de signaler dans le message qu'aucun identifiant de ce type n'existe dans le système est suffisant pour que l'utilisateur puisse reconnaître et résoudre le conflit.
la source
Les autres réponses couvrent tout cela, mais je voulais seulement souligner qu'une erreur de la série 500 signifie "je me suis trompé". Dans ce cas, "I" signifie l'API, donc une erreur de serveur non gérée ou similaire. Une erreur de la série 400 signifie "vous vous êtes trompé" - l'appelant de l'API a envoyé quelque chose d'incorrect.
la source
D'autres utilisateurs ont fourni des réponses valides sur ce qu'il faut faire si vous voulez consulter le livre.
Cependant, je suggérerais que vous lisiez trop dans le RESTful et que vous soyez absolument casher à son égard.
REST est un protocole capricieux, car si vous voulez suivre le livre en l'utilisant, il oblige le client et le serveur à se construire en ayant une connaissance spécifique du fait qu'ils communiquent via REST, donc le protocole de communication spécifique étant essentiellement utilisé ne peut pas être extrait.
Il existe une approche différente: évitez complètement RESTfulness et utilisez-le comme un protocole de communication et rien d'autre. Cela signifie que les seules réponses à renvoyer sont "HTTP 200 OK" et "HTTP 500 Internal Server Error" car, en ce qui concerne le protocole de communication, toute tentative de communication ne peut avoir que deux résultats: soit la requête a abouti. livré au serveur, ou non.
Ce qui se passe après la livraison n’est pas du domaine du protocole de communication. Ainsi, une fois que le serveur a reçu la demande et qu'il commence à la traiter, de nombreuses erreurs peuvent survenir, mais il s'agit toutes d'erreurs spécifiques à l'application qui ne relèvent pas du protocole de communication. Ils devraient être communiqués dans le contexte d'une réponse qui semble parfaitement réussie pour autant que le protocole de communication le sache.
En résumé, je recommanderais donc de renvoyer un "HTTP 200 OK" et, dans la charge de réponse ("contenu de la réponse" en langage HTTP), un code d'erreur spécifique à l'application indiquant "ID non trouvé" ou autre.
la source