Comment choisir un code d'état HTTP dans l'API REST pour "Pas encore prêt, réessayer plus tard"? [fermé]

152

Je développe une API RESTful dans laquelle http://server/thingyapi/thingyblob/1234retourne le fichier (aka "blob") associé à thingy # 1234 à télécharger. Mais il se peut que la demande soit faite à un moment où le fichier n'existe pas sur le serveur, mais il sera certainement disponible ultérieurement. Il y a un processus par lots dans le serveur qui génère tous les blobs pour tous les trucs. Thingy 1234 existe déjà et ses données, autres que le blob, sont déjà disponibles. Le serveur n'a pas encore généré le blob de thingy 1234.

Je ne veux pas retourner 404; c'est pour des trucs qui n'existent pas. C'est une chose qui existe, mais son blob n'a pas encore été généré. Un peu comme une vidéo YouTube qui est en "traitement". Je ne pense pas non plus que les codes de redirection seraient appropriés; il n'y a pas "d'autre" URL à essayer.

Quel est le code d'état HTTP correct à renvoyer dans un tel cas?

JCCyC
la source
3
Un peu lié
Rob Hruska
7
Premièrement, si le thingy 1234 n'a pas encore de représentation GET-able, dans quel sens existe-t-il en tant que ressource (du point de vue du client)? Le fait que, à l'intérieur du serveur, il y ait un travail en file d'attente pour créer 1234, ne semble pas impliquer que la ressource 1234 existe. Deuxièmement, où le client a-t-il obtenu l'URI ... / thingyblob / 1234? Le serveur n'aurait probablement pas dû fournir cet URI au client jusqu'à ce que la ressource soit réellement GET-able.
Andy Dennie
1
Un objet a d'autres propriétés qui valent la peine d'être obtenues autres que le blob. Ce n'est que le blob qui prend du temps à générer. Le client les obtient, par exemple, par le serveur / thingyapi / thingy / 1234
JCCyC
10
La norme HTTP fournit des conseils sur les codes d'état à utiliser pour quelles situations. Cette question n'est donc pas vraiment essentiellement basée sur l'opinion .
Raedwald
2
Que diriez-vous de 204"Aucun contenu"? Est indique que le serveur a traité avec succès la demande et ne renvoie aucun contenu [pour le moment].
Timo

Réponses:

77

Je suggère 202 - Accepted. De la documentation :

La demande a été acceptée pour traitement, mais le traitement n'est pas terminé. [...] Son objectif est de permettre à un serveur d'accepter une demande pour un autre processus (peut-être un processus orienté batch qui n'est exécuté qu'une fois par jour)

matsev
la source
62
-1: Cela aurait du sens pour la requête qui lance le processus qui crée finalement "thingy # 1234", mais pas pour la requête GET émise par la suite pour "thingy # 1234" elle-même. En particulier, un 202 suggère qu'à la suite de la demande GET, le service enverra les données pour "thingy # 1234" à un moment ultérieur. Ce n'est tout simplement pas correct.
Sam Harwell
7
Il dit également: "L'entité renvoyée avec cette réponse DEVRAIT inclure une indication de l'état actuel de la demande et soit un pointeur vers un moniteur d'état, soit une estimation du moment où l'utilisateur peut s'attendre à ce que la demande soit satisfaite.", Donc ce serait un un bon moyen de faire savoir au client que l'objet blob n'est pas encore prêt et un moyen de savoir quand il est prêt.
Remy Lebeau
3
Je dirais que "accepté pour traitement" indique que vous enregistrez la demande pour être traitée plus tard. S'il est simplement ignoré, vous devez renvoyer un code 4xx ou 5xx pour indiquer au client qu'il pourrait vouloir réessayer.
Luc
3
102 (traitement) semble aussi parfois un choix raisonnable même s'il est dans la spécification webdav.
akostadinov
2
Je ne peux pas être plus en désaccord avec cette réponse. Le serveur ne retourne rien, ou ne prévoit pas (ne pas faire de traitement à cause de cette requête - ce qu'il ne devrait de toute façon pas pour un GET). En tant que telle, la ressource n'est d'une certaine manière pas disponible pour le client. Cela doit être traité comme une erreur, donc aucun code 2XX n'est approprié. Quelque chose dans l'espace 4XX ou 5XX. La demande n'a pas été "acceptée pour traitement" , la demande est en pratique rejetée
Adam
53

Le "problème", tel qu'il est, est côté serveur: le client a fait une requête bien formée, mais le serveur ne peut pas la satisfaire. Je suis donc enclin à une "Erreur de serveur", code d'état 5xx.

Quoth RFC 7231 (la norme HTTP actuelle, emphase ajoutée):

La classe de code d'état 5xx (Server Error) indique que le serveur est conscient qu'il s'est trompé ou qu'il est incapable d'exécuter la méthode demandée . Sauf lorsqu'il répond à une demande HEAD, le serveur DEVRAIT envoyer une représentation contenant une explication de la situation d'erreur, et s'il s'agit d'une condition temporaire ou permanente.

Remarque

  • "s'est trompé ou est incapable d'exécuter la requête": malgré leur titre de "Erreur serveur", ils ne sont pas seulement pour les erreurs du serveur.
  • " temporaire ou permanent": ces codes conviennent aux ressources temporairement indisponibles, comme la vôtre.

Parmi les codes disponibles, je dirais 503, «Service indisponible» était le meilleur choix:

Le code d'état 503 (Service non disponible) indique que le serveur est actuellement incapable de traiter la demande en raison d'une surcharge temporaire ou d'une maintenance planifiée, qui sera probablement atténuée après un certain délai. Le serveur PEUT envoyer un champ d'en-tête Retry-After ... pour suggérer une durée appropriée pour que le client attende avant de réessayer la demande.

Remarque:

  • "probablement soulagé après un certain délai": vrai pour votre cas.
  • "surcharge temporaire": pas vraiment vrai pour votre cas. Mais, pourrait-on dire, si votre serveur était beaucoup plus rapide, le traitement par lots aurait déjà été fait lorsque le client a fait la demande, c'est donc une sorte de "surcharge": le client demande des ressources plus rapidement que le serveur ne peut le faire les disponibles.
  • La nouvelle tentative est adaptée à votre service, votre réponse doit donc inclure une Retry-Aftervaleur. Vous pouvez fournir comme valeur le temps d'exécution estimé de la prochaine exécution du traitement par lots ou l'intervalle d'exécution du traitement par lots.

La définition de votre propre code d'état 5xx (591, par exemple), bien qu'autorisée , aurait la mauvaise sémantique:

un client DOIT comprendre la classe de tout code d'état, comme indiqué par le premier chiffre, et traiter un code d'état non reconnu comme étant équivalent au code d'état x00 de cette classe

Les clients traiteraient votre propre code d'état comme 500, "Erreur interne du serveur" , ce qui ne serait pas correct.

Raedwald
la source
2
Je ne vois pas comment c'est mieux que 202: benramsey.com/blog/2008/04/…
JCCyC
4
@JCCyC votre blog est un bon cas pour renvoyer un 202 en réponse à une demande de création de quelque chose (un POST ou PUT). La question semble être de savoir ce qu'il faut retourner pour un GET.
Raedwald
@JCCyC cela pourrait être vu comme une nuance différente de non-prêt-ness: imaginez un ajax à cette ressource, préférez-vous 202 comme statut de réussite ou 503 comme statut d'erreur? afin que vous puissiez voir quel sens vous préférez implicitement dans le contexte de la réaction de votre application à la réponse
rloth
j'aime aussi l'aspect pratique de "Retry-After" qui va bien avec quelque chose qui n'est "pas prêt"
rloth
1
NB: "Retry-After" peut également aller avec 307 - TEMPORARY REDIRECTce qui est bien si vous voulez forcer le côté client à attendre ailleurs pendant que votre ressource est "préparée"
rloth
28

Je pense que 423 - Locked peut être utilisé à cette fin:

Le code d'état 423 (Verrouillé) signifie que la ressource source ou de destination d'une méthode est verrouillée. Cette réponse DEVRAIT contenir un code de précondition ou de post-condition approprié, tel que «lock-token-submit» ou «no-conflicting-lock».

Fernando Ortega
la source
1
Excellente réponse! Je me demande pourquoi il n'y a pas plus de votes positifs.
lex82
10
Peut-être parce que c'est un code HTTP WebDAV?
Stephan L
1
Depuis akka-http, il y a StatusCode RetryWith = reg (c (449) ("Retry With", "La requête doit être réessayée après avoir effectué l'action appropriée.")) Où l'action serait d'attendre et de réessayer
ozma
2
À bien des égards, je suis d'accord avec cela. J'ai une situation similaire (dans mon cas, je cherche à partir d'un index qui n'est peut-être pas encore rempli). Sémantiquement, je pense que c'est correct. Cependant, la RFC pour 423 déclare "Cette réponse DEVRAIT contenir un code de précondition ou de postcondition approprié, tel que 'lock-token-submit' ou 'no-conflicting-lock'." Je ne sais pas comment appliquer cela ici. Et personnellement, j'irais avec 409 Conflict, mais cela a été rejeté sans commentaires - vous ne savez pas pourquoi?
Adam
22

Je ne veux pas retourner 404; c'est pour des trucs qui n'existent pas.

L'URL ne correspond pas à une demande de chose.

http://server/thingyapi/thingyblob/1234

Le client demande un objet thingyblob, qui n'existe pas. S'il existait, vous le leur donneriez.

404.

funroll
la source
1
Je suis content que quelqu'un ait dit ça! Je ne peux pas croire qu'il y ait autant de gens qui pensent que 503c'est une réponse appropriée. Sans parler de certaines des autres suggestions étranges.
Jason Desrosiers
Bien que je convienne qu'un 404 est la réponse la plus appropriée ici, il ne répond pas à la question du PO sur la façon d'indiquer quand le truc est disponible :-). Je pense que le champ Retry-After semble le meilleur candidat, mais il ne peut être utilisé officiellement que pour les codes 503 et 3xx. @Jason: Je pense que cela explique certaines des suggestions étranges.
Ron Deijkers
Je pense que c'est la meilleure réponse. Vous êtes autorisé à renvoyer un corps dans une réponse 404. Le corps pourrait indiquer que le truc sera disponible à une date ultérieure. Ou utilisez également l'en-tête Retry-After. La norme doit être un peu étirée ici car elle ne couvre pas bien ce cas.
WW.
4
Les gens sont devenus trop acclimatés à la page 404 signifiant pas trouvé qu'ils ne peuvent pas logiquement dissocier cela dans le contexte d'une API.
The Muffin Man
1
C'est tellement 404. Thingyblob n'existe pas encore, ou jamais. Pour http, il n'est pas pertinent de savoir s'il sera un jour disponible. Pour le moment, il n'existe pas, et son 404. Quand il sera disponible est un autre problème, qui peut être résolu en poussant un message du serveur au client sayin thingyblob: 1234 available. Effectuez un
retour
21

Une autre option: 503 - Service Unavailable.

Brian Kelly
la source
5
Selon le W3C, ce n'est pas ce que vous voulez dire au client (bien que cela signifie "revenir" d'une certaine manière): "Le serveur est actuellement incapable de gérer la demande en raison d'une surcharge temporaire ou d'une maintenance du serveur. L'implication est que il s'agit d'une condition temporaire qui sera atténuée après un certain délai. Si elle est connue, la longueur du délai PEUT être indiquée dans un en-tête Retry-After. Si aucun Retry-After n'est donné, le client DEVRAIT traiter la réponse comme il le ferait pour un 500 réponses. "
skalee
4
Le service n'est pas indisponible, le service est disponible mais le traitement n'est pas terminé. Donc 503 n'est probablement pas une bonne idée.
Ishtiaque Khan
17

Puisque votre ressource n'est pas prête, vous savez probablement quand (approximativement) elle sera disponible et quand le client pourra réessayer sa demande. Cela signifie que vous souhaiterez peut-être utiliser l'en -tête Retry-After . Cet en-tête est valide avec 503 (Service non disponible), ce qui signifie que tout le site est arrêté pour maintenance, et 3xx (Redirection) réponses.

À mon avis, 302 (trouvé) avec en-tête Retry-After serait la meilleure option, mais je ne suis pas sûr si le champ Location de l'en-tête de réponse peut être égal à l'URL de la demande. C'est une redirection circulaire, de toute façon.

skalee
la source
3
Même si cela est autorisé, si le client n'a pas implémenté la prise en charge de l'en-tête Retry-After, une redirection 3xx vers la même page peut éventuellement se terminer par un 503 ... (éventuellement avec un en-tête Retry-After bien sûr)
Ron Deijkers
1
Retry-After est également valide avec HTTP 429 «Too Many Requests», ajouté par RFC 6585 (avril 2012). Cela peut être approprié si la raison pour laquelle la ressource n'est pas encore prête est que le client a donné trop de travail au serveur.
Silas
8

409 Conflit

Indique que la demande n'a pas pu être traitée en raison d'un conflit dans la demande, tel qu'un conflit d'édition dans le cas de plusieurs mises à jour. [Source Wikipedia.]

Cela pourrait être approprié.

Si vous ne pouvez pas répondre à la demande en renvoyant les données, ce n'est pas un succès. Je pense que 202 suggère que le serveur a mis la demande en file d'attente et qu'il répondra à la demande plus tard. Mais dans votre cas, la demande concerne maintenant des données et a échoué. Si vous réessayez plus tard, il s'agit d'une demande différente.

Je pense que vous avez un conflit .. vous voulez les données .. mais c'est en cours d'édition / mise à jour. Ce serait également le cas si Thingy1234 existait déjà et avait été téléchargé avec succès auparavant, mais qu'il était maintenant en cours de modification, qu'il n'était pas disponible pendant la modification.

J Moore
la source
2
Je ne sais pas pourquoi cela a été rejeté. Cela me semble être la bonne réponse. Extrait de la RFC: "Le code d'état 409 (Conflit) indique que la demande n'a pas pu être exécutée en raison d'un conflit avec l'état actuel de la ressource cible. Ce code est utilisé dans les situations où l'utilisateur pourrait être en mesure de résoudre le conflit et resoumettez la demande. "Vous avez demandé une ressource que le serveur ne peut pas renvoyer car le serveur est en train de mettre à jour cette ressource - c'est-à-dire en raison de l'état actuel de la ressource. Le client peut résoudre ce problème en attendant et en soumettant à nouveau
Adam
1
@Adam Je pense que l'implication dans "l'utilisateur pourrait être en mesure de résoudre le conflit" est que quelque chose au sujet de la nouvelle soumission serait différent, autre que juste attendre.
Développeur holistique
3

501 - Non mis en œuvre

Exactement comme ça sonne. Une fonctionnalité qui n'est pas encore implémentée, mais qui implique une disponibilité future.

Voici un lien vers un résumé des erreurs 5xx .

Dan
la source
4
Pour cette question, il semble que la fonctionnalité elle-même existe, mais pas l'élément demandé.
Luc
La description de @Luke 501 à partir du lien dans ma réponse, `` ... il n'a pas la capacité de répondre à la demande. Cela implique généralement une disponibilité future ». Cela répond exactement à ce que le PO demandait. Que les données soient présentes ou non sur ses serveurs ou sa base de données. Le résultat final est qu'il n'est pas accessible via l'API pour le moment. Par conséquent, l'API ne peut pas répondre à la demande, mais souhaite impliquer qu'elle sera disponible à l'avenir via le code http.
Dan