web-dev-qa-db-fra.com

Code d'état HTTP pour réessayer la même demande

Existe-t-il un code d'état HTTP pour demander à un client d'effectuer à nouveau la même demande?

Je suis confronté à une situation où le serveur doit "attendre" la disparition d'un verrou lors du traitement d'une demande. Mais au moment où le verrou disparaît, les demandes pourraient être proches de son délai d'expiration. Donc, au lieu de cela, une fois le verrou effacé, je voudrais demander au client de simplement effectuer à nouveau la même demande.

Le mieux que je puisse trouver est un HTTP 307 au même endroit, mais je crains que certains navigateurs n'y adhèrent pas (détection de boucle de redirection).

27
Jeroen

La réponse correcte , lorsqu'un serveur est incapable de gérer une demande, est 503 Service non disponible . Lorsque la condition est temporaire, comme dans votre cas, vous pouvez définir Retry-After en-tête pour indiquer au client combien de temps il doit attendre avant de réessayer.

Cependant, cela ne forcera pas le navigateur à exécuter à nouveau la demande - c'est quelque chose que vous devrez gérer vous-même en javascript. Par exemple, voici comment vous pouvez effectuer une nouvelle tentative ajax POST request in jquery:

function postData() {
  $.ajax({
    type: 'POST',
    url:  '503.php',
    success: function() {
      /*
         Do whatever you need to do here when successful.
      */
    },
    statusCode: {
      503: function(jqXHR) {
        var retryAfter = jqXHR.getResponseHeader('Retry-After');
        retryAfter = parseInt(retryAfter, 10);
        if (!retryAfter) retryAfter = 5;
        setTimeout(postData, retryAfter * 1000);
      }
    }
  });
}

Notez que le code ci-dessus prend uniquement en charge un Retry-After en-tête où le délai de relance est spécifié en secondes. Si vous voulez soutenir des dates qui nécessiteraient un peu plus de travail. Dans le code de production, je recommanderais également un compteur quelconque pour vous assurer de ne pas réessayer indéfiniment.

Quant à l'utilisation d'un code d'état 307 pour répéter la demande automatiquement, je ne pense pas que ce soit une bonne idée. Même si vous ajoutez un paramètre de nouvelle tentative pour contourner la détection de boucle du navigateur (qui ressemble à un horrible hack), cela ne fonctionnera toujours pas sur une demande POST. From RFC2616 :

Si le code d'état 307 est reçu en réponse à une demande autre que GET ou HEAD, l'agent utilisateur NE DOIT PAS rediriger automatiquement la demande à moins qu'elle ne puisse être confirmée par l'utilisateur.

Bien que certains navigateurs soient connus pour ignorer cette exigence, ce n'est certainement pas correct et ce n'est pas quelque chose sur lequel vous voudriez vous fier.

Et si vous n'utilisez pas une demande POST, vous devriez certainement l'être. N'oubliez pas qu'une demande GET ne devrait pas avoir d'effets secondaires , et par défaut la réponse sera mis en cache. D'après la description de votre problème, il semble que votre demande soit susceptible de provoquer des effets secondaires.

31
James Holderness

Utilisez la redirection 307, mais ajoutez un compteur de nouvelles tentatives:

http://path/to/server?retry=3

Cela rendra l'URL différente à chaque nouvelle tentative, empêchant la détection de boucle. Et le serveur pourrait vérifier si une nouvelle tentative a atteint une limite et abandonner avec une erreur lorsque cela se produit, afin que l'utilisateur n'attende pas indéfiniment.

3
Barmar