web-dev-qa-db-fra.com

«Aucun résultat» doit-il être une erreur dans une réponse RESTful?

Je vais décrire un exemple:
Je commence à créer une API pour une boulangerie. L'API permettra aux utilisateurs de rechercher dans leur catalogue des produits de boulangerie, tels que des biscuits aux pépites de chocolat faits maison à l'aide de api.examplebakery.com/search?q=......

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

Doit-il être renvoyé comme une erreur? La recherche n'a pas échoué, l'API a recherché et conclu avec succès qu'aucun cookie n'a pu être trouvé. L'API ne doit pas renvoyer 404, car l'API a bien été trouvée.

54
Berry M.

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

Donc, si votre réponse est normalement la suivante:

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

Ensuite, pour une requête avec 0 résultats, ce 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ère de dire qu'il y a 1 "page".

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

204 No Content peut également sembler être une option, mais ce n'est pas parce que vous renvoyez en fait du "contenu" - la liste vide. Si vous pensez qu'une liste vide ne compte pas comme "contenu", que se passe-t-il si vous modifiez ensuite la réponse pour proposer des suggestions d'orthographe? 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, jpmc26 a une réponse vaut la peine d'être lu.

125
Jory Geerts

Chaque fois que vous décidez d'un code HTTP, vous devriez toujours poser cette question:

Que peut/voudra/devrait faire un client arbitraire 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 provient de l'entrée du client ou des processus du serveur.
  2. Le client doit-il plutôt faire une demande ailleurs? Alors 3xx est fait 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 en premier. Cela élimine rapidement de nombreux codes de réponse en option et (peut-être plus important encore), il est beaucoup plus simple de suivre la sémantique des codes. Voir les premières sections de la documentation du code HTTP pour les explications de ce que chaque catégorie de codes représente.

Dans ce cas, le client a demandé une liste de résultats avec un filtre à partir d'un point de terminaison existant et 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), si bien que la demande a 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 s'agit en quelque sorte d'un problème pour le code client, c'est la responsabilité du client de déterminer, vérifier et gérer de manière appropriée. Il s'agit donc clairement de 2xx.

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

  • Voulez-vous renvoyer une représentation d'une liste vide, comme quelques autres réponses décrire? Si c'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 pour le client à consommer. C'est probablement le moyen le plus pratique de répondre pour vos consommateurs, qui peuvent simplement analyser la réponse s'il y a eu des résultats ou non, puis déterminer eux-mêmes comment gérer une liste vide.
  • 204 n'est pas sémantiquement faux ici, mais vous devrez répondre avec aucun corps de message que ce soit . Cela signifie que tout le code client devrait vérifier explicitement les différents codes HTTP (ou au moins l'absence de corps de message) et les traiter séparément. C'est gênant et plus susceptible de conduire à des clients mal comportés.

Les autres ne s'appliquent pas du tout:

  • 201 est hors de question. Vous n'avez créé aucune ressource persistante et ne renvoyez 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é, donc cela ne s'applique pas ici.
  • 205 n'a pas de sens. Vous n'avez pas besoin que le client efface ou rafraîchisse quoi que ce soit.
  • 206 semble être conçu pour renvoyer une grande ressource sur plusieurs réponses. Cela nécessite également que le client demande une partie du contenu dans les en-têtes (donc la pagination via les chaînes de requête n'est pas admissible). Ne s'applique pas ici.

Il doit donc être 200 ou 204, et 200 est plus susceptible de conduire à un code client plus simple et plus robuste (surtout si vous utilisez une structure de réponse cohérente contenant une liste vide).

39
jpmc26

Non. L'utilisation de 404 pour indiquer "votre requête a été traitée mais il n'y a pas de correspondance" est affreuse car:

  • 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 maladroite)

  • ambiguïté entre la "vraie" page introuvable, vous avez tapé les erreurs de point final

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

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

16
Ewan

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

Si la requête est du type qui renvoie un ensemble de résultats, alors l'ensemble vide est logiquement tout aussi approprié qu'un ensemble de un ou un ensemble de plusieurs. D'une manière générale, pour les raisons exposées par @Ewan, il est plus néfaste que bénéfique de transformer l'ensemble vide en erreur et ce n'est tout simplement pas nécessaire.

Si la requête est du type qui recherche et renvoie un singleton spécifique (qui devrait être trouvé, par exemple une correspondance exacte par id), alors non trouvé est une réponse possible logiquement appropriée.

9
Erik Eidt

Vous supposez que le code doit effectuer une action 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 certain nombre de choses. Vous ne devez donner à un utilisateur une "erreur" que s'il y a effectivement une erreur.

5
John Smith

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 veut pour traiter différemment, et un succès dans les situations que le client veut pour traiter la même chose.

Si je fais une requête qui pourrait en théorie retourner n'importe quel nombre de résultats, zéro, un, deux cent et ainsi de suite, alors vous devriez retourner "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 beaucoup de résultats, vous avez renvoyé une liste partielle de résultats pour éviter une taille excessive, et il y a une façon convenue d'obtenir les autres résultats. C'est parce qu'en tant que client, je veux souvent gérer le cas de zéro résultat comme le cas de plus de résultats. Je pourrais le traiter différemment, mais je ne veux pas y être forcé.

C'est différent dans le cas où je recherche une valeur. J'attends exactement un résultat, la valeur que je recherche. Et j'ai besoin de ce seul résultat pour continuer ce que je veux faire de manière significative. Ici, il est beaucoup plus acceptable de renvoyer un état 404 pour le cas où aucune valeur n'est là, car j'ai quand même besoin de gérer ce cas différemment.

Résumé: Si le client attend un certain nombre de résultats, de zéro à un grand nombre, retourne "succès" si tous les résultats sont fournis, même si le nombre est nul. Si le client attend exactement un résultat, retournez succès si le résultat est trouvé et une erreur si le résultat n'est pas trouvé.

0
gnasher729