“Aucun résultat” doit-il être une erreur dans une réponse RESTful?

52

Je vais décrire un exemple:
je commence à créer une API pour un magasin de pâtisserie. L'API permettra aux utilisateurs de rechercher dans leur catalogue des produits de cuisson, tels que les biscuits faits maison aux pépites de chocolat et à la menthe api.examplebakery.com/search?q=......

Quelqu'un l'utilise pour rechercher un produit nommé pineapple-banana flavoured cookieset ne trouvera évidemment aucun résultat.

Cela devrait-il être retourné comme une erreur? La recherche n’a pas échoué, l’API a effectué la recherche et a conclu qu’aucun cookie n’était trouvé. L'API ne doit pas revenir 404, car l'API a bien été trouvée.

Berry M.
la source
51
204 Pas de contenu
AakashM
6
La duplication possible de l' API RESTful représente l'absence de quelque chose
gnat le
3
@gnat: Il ne s'agit pas d'un doublon car l'autre question concerne une ressource spécifique et non une requête sur plusieurs ressources.
Greg Burghardt le
7
De manière analogue, supposons que vous ayez une fonction qui retourne un tableau d'objets. S'il n'y a pas d'objets correspondant à un cas d'utilisation particulier, préféreriez-vous que la fonction passe par une exception ou renvoie un tableau vide?
Kevin - Réintégrer Monica le
2
@AakashM Renvoyer HTTP-204 à une requête GET est assez inhabituel, je sais que je ne l'ai vu nulle part. Autant que je sache, HTTP-204 est généralement utilisé comme réponse lors de la modification d'une ressource sur le serveur, par exemple des demandes POST / PUT / DELETE.
Radu Murzea

Réponses:

122

Lorsqu'il y a des résultats, le résultat est une liste (JSON, basée sur votre commentaire). Pour les requêtes sans résultat, le résultat devrait être exactement le même. La liste simple contient 0 éléments.

Donc, si votre réponse est normalement ceci:

{
    "results": [
        {
            "name": "Pancakes",
            ....
        },
        {
            "name": "French Fries",
            ....
        }
    ]
}

Ensuite, pour une requête avec 0 résultats, cela devrait être ceci:

{
    "results": []
}

Si vous incluez également des métadonnées sur le nombre de "pages" de résultats, des liens vers ces "pages", etc., je vous suggérerais alors de définir 1 "page".

Le statut HTTP doit être le même que lorsqu'il y a des résultats - 200 OK.

204 No ContentCela peut aussi sembler être une option, mais ce n’est pas parce que vous retournez en fait du "contenu" - la liste vide. Si vous estimez qu'une liste vide ne compte pas comme "contenu", si vous modifiez ensuite la réponse pour proposer des suggestions orthographiques? Le noyau de la réponse sera toujours une liste vide, mais maintenant il y a encore plus de "contenu".

Pour plus d'informations utiles sur les codes d'état HTTP, la réponse de jpmc26 mérite d'être lue.

Jory Geerts
la source
9
C'est le même genre de pensée que le modèle d'objet nul . Les erreurs et null ne sont pas le seul moyen de dire qu'il n'y a rien ici. Parfois, vous voulez exprimer votre rien tranquillement. De cette façon, les clients n'ont pas à tester pour rien.
candied_orange
54
Je dirais que renvoyer un 204 est inapproprié, car vous renvoyez du contenu. C'est juste que le contenu n'a aucun résultat, ce qui est distinct de ne renvoyer aucun contenu.
TMN
9
@TMN a accepté - 204 n'est pas approprié pour "aucun résultat". Votre requête doit toujours renvoyer un tableau, avec les résultats à l'intérieur du tableau. S'il n'y a pas de résultat, le client s'en chargera naturellement. Si le client souhaite afficher un texte spécial ("Aucun résultat n'a été trouvé"), c'est très bien. 204 ne doit être renvoyé que pour un noeud final qui ne renvoie pas naturellement un résultat.
JasonB
1
Vous pourriez utiliser 204 si vous retourniez une valeur null sérialisée en tant que chaîne vide Je reconnais
Ewan
15
Cette. L'important lors de la construction d'une API RESTful est la partie API, pas la tranquillité. Une bonne API facilite la vie des clients / consommateurs. Un tableau vide est plus facile à gérer que des valeurs / exceptions / codes d'état nuls.
Guran
37

Chaque fois que vous choisissez un code HTTP, vous devez toujours poser cette question:

Que peut / voudra / devrait tout client arbitraire faire avec la réponse?

  1. Le client doit-il toujours traiter la réponse comme un échec? Ensuite, vous voulez 4xx ou 5xx, selon que le problème concerne l'entrée du client ou les processus du serveur.
  2. Le client doit-il faire une demande ailleurs? Alors 3xx est pour vous.
  3. Le serveur a-t-il fait ce que le client a demandé (réussi)? C'est 2xx.

Décidez toujours dans quelle plage votre code de réponse doit être placé en premier. Faire si rapidement élimine un grand nombre de codes de réponse en tant qu'options, et (peut-être plus important encore) il est beaucoup plus simple de suivre la sémantique des codes. Voir les sections de début de la documentation du code HTTP pour des explications sur ce que chaque catégorie de codes représente.

Dans ce cas, le client a demandé une liste de résultats avec un filtre provenant d'un noeud final existant valide et a l'autorisation d'y accéder. Le serveur a pu traiter la demande et déterminer les données appropriées à renvoyer (aucun élément). La demande a donc abouti. Il se trouve que le filtre qu'ils ont donné a filtré tous les résultats. Il n'appartient pas au serveur de déterminer si c'est ce que le client voulait ou non, car cela peut être un résultat attendu pour certains clients. S'il y a un problème pour le code client, c'est au client qu'il incombe de déterminer, vérifier et gérer de manière appropriée. Donc, c'est clairement 2xx.

Maintenant, la question est: "Quel 2xx?" Cela dépend de la façon dont vous souhaitez que le serveur réponde.

  • Allez-vous renvoyer une représentation d'une liste vide, comme le décrivent d' autres réponses ? Si tel est le cas, vous voulez 200. 200 signifie que le serveur n'a rencontré aucun problème et a une représentation des résultats à utiliser par le client. C’est probablement le moyen le plus pratique de répondre pour vos clients, qui peuvent simplement analyser la réponse, qu’il obtienne des résultats ou non, puis déterminer comment gérer eux-mêmes une liste vide.
  • 204 n’est pas sémantiquement faux ici, mais vous auriez à répondre sans corps du message . Cela signifie que tout le code client devrait explicitement rechercher différents codes HTTP (ou au moins l'absence de corps de message) et les gérer séparément. C'est peu pratique et plus susceptible de conduire à des clients mal élevés.

Les autres ne sont pas applicables du tout:

  • 201 est hors de question. Vous n'avez créé aucune ressource persistante et vous ne rendez pas d'emplacement à une ressource créée.
  • 202 est hors de question. La demande est faite; ce n'est pas un traitement en arrière-plan.
  • 203 signifie que la réponse a été modifiée entre le serveur faisant autorité et le client. Votre interface RESTful est le serveur faisant autorité, ce qui ne s'applique pas ici.
  • 205 n'a pas de sens. Vous n'avez pas besoin du client pour effacer ou actualiser quoi que ce soit.
  • 206 semble être conçu pour renvoyer une ressource volumineuse sur plusieurs réponses. Il faut également que le client demande une partie du contenu dans les en-têtes (la pagination via des chaînes de requête ne peut donc pas être qualifiée). Non applicable ici.

Il doit donc être soit 200, soit 204, et 200 entraînera probablement un code client plus simple et plus robuste (en particulier si vous utilisez une structure de réponse cohérente contenant une liste vide).

jpmc26
la source
5
Serait intéressé par l'opinion de downvoter. Je ne pense pas que cela soit controversé.
jpmc26
2
Je ne pense pas que les clients doivent vérifier 204 explicitement. Tout ce dont ils ont besoin est la capacité de gérer un objet à réponse nulle. C'est le travail de la structure HTTP de gérer 204 en ignorant la partie "analyser le corps". 200 avec Content-Lenght 4 et body null est identique.
Agent_L
1
@Agent_L Vous avez raison de dire que si le serveur répond avec une structure incohérente par rapport à la réponse normale (par exemple, placer nullune liste dans le cas contraire), vous ne récolterez pas les avantages de la cohérence, même avec 200. Cependant, ce que je décris utilise une réponse cohérente avec la structure normale et contenant une liste vide dans laquelle la liste des résultats devrait normalement aller. 204 enlève toute possibilité d'avoir une réponse aussi cohérente. De même, même dans les bibliothèques de clients HTTP dotées de fonctions pratiques, vous devez (généralement?) Faire un appel explicite pour analyser JSON.
jpmc26
@Agent_L En particulier avec les listes, les appelants peuvent souvent laisser leur code s'exécuter normalement sur une liste vide (en faisant une boucle dessus, par exemple), alors qu'ils auraient besoin d'une vérification explicite pour gérer un autre type de représentation.
jpmc26
16

L'utilisation de 404 pour indiquer "votre requête a été traitée mais il n'y a pas eu de correspondance" est horrible pour les raisons suivantes:

  • flux conditionnel basé sur la gestion des exceptions (c'est-à-dire forcer un résultat non exceptionnel à créer et à gérer une exception dans le client qui peut être non performante et gênante)

  • ambiguïté entre la 'vraie' page non trouvée, vous avez tapé les erreurs erronées au point final

Ce qu'il faut retenir, c'est qu'il y a toujours un client pour désérialiser le message et que ce qu'il retourne est important; pas la sérialisation.

Si le client doit renvoyer null, utilisez la sérialisation de null. Si le client doit renvoyer un tableau vide, utilisez [], s'il envoie une erreur, utilisez 500 et transmettez le message d'erreur.

Ewan
la source
2
Pourquoi le serveur doit-il veiller à ce que le client fait avec les informations? (PS: Je ne suis pas celui qui a réduit votre réponse).
Radu Murzea
dans ce contexte, le "client" est le code exécuté sur le périphérique client qui expose le service à l'application cliente. Il doit pouvoir exposer les méthodes de service et renvoyer les résultats comme prévu par le service. Vous avez besoin d'une paire client-serveur pour que la communication fonctionne
Ewan
3
N'utilisez bien sûr pas 5xx pour les erreurs client . Préférez 4xx dans ce cas.
Kevin
1
Bien que cela ne devrait pas être "serveur", pas "client" dans la plupart de ces cas? C'est le serveur qui traite la demande et envoie une réponse, le client ne fait que traiter la réponse? Dans quel cas un code 5xx serait OK, car c'est une erreur de serveur, pas une erreur de client?
MrWhite
2
le problème avec tous les codes d'erreur est qu'ils ont une signification dans http. 500 est le seul code qui convient lorsque votre service lève une exception
Ewan
9

Au-delà de la très bonne réponse de @ Ewan:

Si la requête est du genre qui renvoie un ensemble de résultats, alors l'ensemble vide est logiquement tout aussi approprié qu'un ensemble de un ou de plusieurs. De manière générale, pour les raisons évoquées par @Ewan, modifier le jeu vide en une erreur fait plus de tort que de mal, ce qui est tout simplement inutile.

Si la requête est du type qui recherche et renvoie un singleton spécifique (que l'on s'attend à trouver, par exemple, la correspondance exacte par id), alors non trouvé est une réponse possible logiquement appropriée.

Erik Eidt
la source
Oui, je pensais exactement cela sur la réponse d'Ewan.
Walfrat
5

Vous supposez que le code doit prendre une mesure spéciale lorsqu'aucune donnée n'est renvoyée, mais ce n'est peut-être pas le cas. Le code peut simplement rechercher un nombre de produits ou ajouter les résultats à une liste ou à un nombre important d'éléments. Vous ne devriez donner à un utilisateur une "erreur" que s'il y a réellement une erreur.

John Smith
la source
3
"Vous ne devriez donner à un utilisateur une" erreur "que s'il y a réellement une erreur." - cette. Un résultat vide défini lors d'une "recherche" n'est normalement pas une "erreur". Toutefois, si la connexion à la base de données échouait, la recherche ne pouvait en réalité être effectuée, un ensemble de résultats vide (et aucune erreur) serait par ailleurs ambigu. Une sorte d'état d'erreur serait approprié dans ce cas (peut-être avec un ensemble de résultats vide - en fonction de la définition de l'API).
MrWhite
0

Lorsque j'utilise une API, en tant que client, je dois gérer des cas de "réussite" différents des cas "d'erreur". Je n'ai pas le choix là-bas. Par conséquent, vous devez renvoyer une erreur dans les situations que le client souhaite traiter différemment et réussir dans les situations que le client souhaite traiter de la même manière.

Si je fais une requête qui pourrait théoriquement renvoyer un nombre quelconque de résultats, zéro, un, deux cents, etc., vous devriez alors renvoyer "succès" chaque fois que l'API fournit la liste complète de tous les résultats. Et peut-être dans les cas où il y a plusieurs résultats, vous avez renvoyé une liste partielle des résultats pour éviter une taille excessive, et il existe un moyen convenu d'obtenir les autres résultats. En effet, en tant que client, je souhaite souvent gérer le cas de résultats nuls, comme le cas de résultats plus nombreux. Je pourrais le traiter différemment, mais je ne veux pas être obligé de le faire.

Il en va différemment dans le cas où je cherche une valeur. J'attends exactement un résultat, la valeur que je recherche. Et j'ai besoin de ce résultat pour continuer ce que je veux faire de manière significative. Ici, il est beaucoup plus acceptable de renvoyer un statut 404 pour le cas où aucune valeur n’y figure, car j’ai quand même besoin de traiter ce cas différemment.

Récapitulatif: si le client attend un nombre quelconque de résultats, allant de zéro à un nombre élevé, renvoyez "succès" si tous les résultats sont livrés, même si le nombre est zéro. Si le client attend exactement un résultat, retournez success si le résultat est trouvé et une erreur si le résultat est introuvable.

gnasher729
la source