Imaginez une API pour identifier si une personne a sélectionné son animal spirituel. Ils ne peuvent avoir que zéro ou un animal spirituel.
Actuellement:
/person/{id}/selectedSpiritAnimal
quand ils ont sélectionné un animal retourne http 200 et {selectedAnimal:mole}
mais quand ils n'ont aucune sélection, il renvoie http 404.
Cela rend mon animal spirituel malheureux car nous représentons une préoccupation de domaine valide - n'ayant pas encore sélectionné un animal spirituel - comme une erreur HTTP.
De plus, en tant qu'entreprise - erm Sprit-Animal-Hampers-R-us - nous voulons savoir quand quelqu'un n'a pas de sélection afin que nous puissions les inciter.
Quelle est une meilleure réponse ici:
HTTP 200 et {selectedAnimal:null}
ou encore plus explicite
HTTP 200 et {selectedAnimal:null, spiritAnimalSelected: false}
Ou vaut-il mieux retourner une 404? Comme un peu comme this image has not yet been uploaded
lors de la visualisation d'une image en ligne serait un 404. this person has not selected a spirit animal
pourrait être un 404
Cette question a été proposée en tant que doublon, mais elle concerne une URL par ailleurs valide qui est demandée lorsque l'application a été configurée pour ne pas autoriser la modification que l'URL représente.
Alors que je regarde ici comment on représente une ressource où l'absence de la ressource est significative. C'est-à-dire qu'il est valide pour le client de demander l'URL et la réponse est que vous avez réussi à demander la ressource qui représente une absence de chose.
Il ne s'agit donc pas d'une `` logique commerciale '' mais plutôt d'une circonstance où l'absence de chose a un sens (il se peut que beaucoup de mes collègues soutiennent que 404 est toujours correct) mais je ne sais pas comment faire correspondre cela au spec.
Très difficile de choisir une réponse. J'ai changé d'avis plusieurs fois au cours de la conversation ici et de celle en cours au travail.
Ce qui m'arrange ici, c'est que la spécification dit qu'un 4xx, c'est quand le client s'est trompé . Dans ce cas, le client a été invité à attendre une réponse de l'URL selectedSpiritAnimal et n'a donc pas commis d'erreur.
Le consensus parmi mes collègues est que c'est le symptôme d'une mauvaise conception d'API
Il serait probablement préférable que nous demandions simplement / person / {id} et cela renvoie un ensemble de relations de lien pour la personne ... alors si vous ne recevez pas le lien / selectedSpiritAnimal (quand une personne n'a pas de sélection) mais vous appelez-le de toute façon alors un 404 a du sens. Ou que vous implémentiez des réponses partielles et que / person / {id} retourne un document plus complet à moins que le client ne demande un sous-ensemble des données
Réponses:
Les codes HTTP 4xx ne sont probablement pas le bon choix pour ce scénario. Vous déclarez que le fait d'avoir zéro animal spirituel est un état valide, et la route API
person/{id}/selectedSpiritAnimal
tiendra compte du fait que la personne enid
possède ou non.Les réponses HTTP 4xx sont réservées à la situation où un client a fait quelque chose de incorrect dans la demande (voir l'archive w3 de la spécification d'origine ). Mais le client fait une demande valable, que la personne
id
ait ou non un animal spirituel.Je me penche donc vers les deuxièmes solutions en utilisant un corps JSON correctement formaté dans la réponse et un code HTTP 2xx.
Maintenant, si vous obtenez une telle demande et qu'il s'avère que personne
id
n'existe, un code 4xx a plus de sens.la source
cases in which the client seems to have erred
, mais d'autre part, la 404 dit directementThe server has not found anything matching the Request-URI
. Vous pourriez envisager de demander quelque chose qui n'existe pas une erreur client. Je comprends que la personne n'existe pas contre un accessoire secondaire qui n'existe pas, mais cela pourrait être indiqué comme message de réponse. 204 semble également pertinent, puisque l'entité existe, mais n'a pas de contenu pour une sous-propriété.Permettez-moi de vous présenter le modèle de maturité Richardson .
Votre problème est que vous représentez deux ressources comme une seule, où vous devriez vraiment avoir deux ressources qui ont une relation indiquée par l'hypermédia. Utiliser l'hypermédia pour décrire les relations est le glorieux niveau 3 de repos.
Votre personne doit vivre sous l'URI
/person/{id}
et l'animal doit vivre sous/spiritanimal/{id}
. La personne doit indiquer qu'elle a un animal spirituel en utilisant un lien vers l'animal.Imaginons une personne appelée Bob, qui a l'identifiant 123 et un animal spirituel Licorne.
GET /person/123
retournerais;
Maintenant, quiconque lit la personne 123 saura qu'il a un animal spirituel et a l'URI où il peut obtenir plus d'informations à ce sujet.
GET /spitiranimal/789
pourrait revenir
Imaginons maintenant une personne appelée Fred, qui a l'identifiant 456 et aucun animal spirituel.
GET /person/456
retournerais;
Maintenant, quiconque lit la personne 456 saura qu'il n'a pas d'animal spirituel, car il n'y a pas de lien. Il n'est pas nécessaire d'utiliser un code d'état HTTP pour représenter l'absence de relation.
la source
Ceci est l'URL appropriée pour obtenir des animaux spirituels; par conséquent, une erreur 404 est inappropriée. 404 est pour représenter un problème technique, pas un problème logique.
La solution appropriée consiste à renvoyer http 200 et
{"selectedAnimal": null}
Vous devriez avoir une méthode Web séparée
/person/{id}/hasSelectedSpiritAnimal
qui revient{"isSpiritAnimalSelected": false}
. Dans les coulisses, il peut ou non faire les mêmes appels de méthode, renvoyant simplement false si null, mais c'est à lui de décider, pas au code consommateur.Il est préférable d'éviter de combiner pour séparer les requêtes en une seule méthode Web sans raison impérieuse de le faire, même si les requêtes sont étroitement liées.
la source
When you said "the spirit animal is not currently on file", it seemed quite similar to me to "there is no content"
Aucun contenu ne signifie aucun contenu . ie: il retourne "". Ces deux ne sont pas du tout similaires. "l'animal spirituel n'est pas actuellement dans le dossier" est très différent de "".Ce que votre point final représente n'est pas seulement un animal; c'est un animal ou son absence. C'est une valeur mieux représentée par un
Optional
/Maybe
/Nullable
/ etc.Les valeurs légitimes (comme dans 200 OK) peuvent donc être:
{'animal': <some animal>, 'selected': true}
{'animal': null, 'selected': false}
Je pourrais imaginer que la
DELETE
méthode, lorsqu'elle est appliquée sur le point de terminaison, peut définir'selected'
àfalse
nouveau, qui est, UNSET l'animal sélectionné.Vous pouvez, bien sûr, déposer la
'selected'
clé ici, elle n'est affichée que pour plus de clarté; string vsnull
suffit pour la distinction.la source
Vous devez utiliser 404.
Puisque vous créez une interface de programmation, pas une interface humaine, le texte 404 est facultatif.
Je préfère cela parce que je préfère autant que possible les protocoles standard. HTTP a un moyen de représenter la non-existence, et c'est ce que j'utiliserais.
EDIT: Supposons que vous ayez ajouté une fonctionnalité permettant aux utilisateurs de choisir de partager leurs animaux spirituels et que personne ne les partage. Souhaitez-vous retourner 200 OK
null
ou 200 OK"Unauthorized
? Ou utiliseriez-vous le standard 401 Unauthorized / 403 Forbidden? Cela semble directement analogue à ne pas en choisir un en premier lieu.Alternativement, si vous souhaitez utiliser 200 OK + JSON, vous devez revenir
null
.Gardez les choses propres. Créez plus d'emballage seulement si nécessaire.
la source
null
(sans valeur). Ceci est différent du client qui demande quelque chose pour lequel il n'existe aucun emplacement pour contenir la valeur. Vous ne suggéreriez pas de lancer unAttributeError
en Python lorsque la valeur se trouve êtreNone
; cela rendrait l'interface peu pratique et inutilement difficile à utiliser. Plus pragmatique, de nombreuses API client HTTP peuvent convertir le 404 en mécanisme de gestion des erreurs standard du langage (code d'erreur, exception, type d'erreur), ce qui signifie que vous devrez supprimer une erreur superflue./person/{id}/selectedSpritAnimal
-à- d . Observer la faute de frappe dansSprit
)./person/{id}/isSpiritAnimalSelected
qui indiquerait au client s'il a été sélectionné. Semble pour moi le même exemple classique de tester si un fichier existe avant de le lire. Il suffit de lire le fichier et de gérer l'erreur ENOENT s'il est levé./person/{id}/selectedSpiritAnimal
est destiné à être utilisé même si l'animal spirituel n'existe pas. Cela signifie que HTTP 4xx est incorrect, lorsqu'il est utilisé dans un tel cas. Op indique également correctement que cela peut être une odeur de mauvaise conception de l'API.