2013-07-25 13 views
20

Czy istnieje kod stanu HTTP, aby polecić klientowi ponowne wykonanie tego samego żądania?Kod stanu HTTP do ponowienia tego samego żądania

Mam do czynienia z sytuacją, w której serwer musi "czekać", aż blokada zniknie podczas przetwarzania żądania. Ale do czasu, gdy blokada zniknie, żądania mogą być zbliżone do limitu czasu oczekiwania. Zamiast tego, gdy blokada zostanie wyczyszczona, chciałbym poinstruować klienta, aby ponownie wykonał tę samą prośbę.

Najlepszym rozwiązaniem jest HTTP 307 w tej samej lokalizacji, ale obawiam się, że niektóre przeglądarki nie mogą tego kupić (wykrywanie pętli przekierowania).

+1

Dodaj zmienny parametr adresu URL, aby nie wyglądał jak pętla. – Barmar

+0

Dobre odpowiedzi na http://stackoverflow.com/q/9794696/520567 (202 and 423) – akostadinov

Odpowiedz

24

Odpowiedź, gdy serwer nie może obsłużyć żądania, to 503 Service Unavailable. Gdy warunek jest tymczasowy, tak jak w twoim przypadku, możesz ustawić nagłówek Retry-After, aby poinformować klienta, jak długo powinien czekać, zanim spróbujesz ponownie.

Nie spowoduje to jednak, że przeglądarka ponownie wykona żądanie - jest to coś, co trzeba by obsługiwać w javascript. Na przykład, oto jak można wykonać żądania POST ponawianie ajax w 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); 
     } 
    } 
    }); 
} 

Zauważ, że powyższy kod obsługuje tylko Retry-After nagłówek jeżeli opóźnienie ponawiania jest podany w sekundach. Jeśli chcesz obsługiwać daty, które wymagają trochę więcej pracy. W kodzie produkcyjnym poleciłabym też pewien rodzaj kontuaru, aby upewnić się, że nie będziesz musiał powtarzać na zawsze.

Jeśli chodzi o użycie kodu statusu 307, aby automatycznie powtórzyć żądanie, nie sądzę, że jest to dobry pomysł. Nawet jeśli dodasz parametr ponowienia, aby obejść wykrywanie pętli przeglądarki (co wydaje się być okropnym hackerem), nadal nie będzie działać na żądanie POST. Od RFC2616:

przypadku otrzymania kodu 307 stanu w odpowiedzi na wniosek innego niż GET lub HEAD, agent użytkownika NIE automatycznie przekierować żądanie, chyba że może on zostać potwierdzony przez użytkownika.

Podczas gdy niektóre przeglądarki ignorują ten wymóg, zdecydowanie nie jest to poprawne i nie jest czymś, na czym chciałbyś polegać.

Jeśli nie korzystasz z żądania POST, prawie na pewno powinieneś. Pamiętaj, że żądanie GET should not have any side effects i domyślnie odpowiedź zostanie zapisana w pamięci podręcznej. Z opisu twojego problemu wynika, że ​​twoja prośba prawdopodobnie będzie robiła coś, co ma skutki uboczne.

+0

Nie sądzę, że błąd serwera jest poprawną odpowiedzią tutaj. Dla mnie coś w gamie 4xx byłoby bardziej sensowne. Czytam http://stackoverflow.com/q/9794696/520567 - tam 423 jest dobre dla przypadku użycia ops. Również 202 jest dobre dla innych przypadków użycia. – akostadinov

3

Używaj 307 przekierowanie, ale dodać licznik powtórzenie:

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

To sprawi, że każdy na inny adres URL ponownie, co uniemożliwia wykrycie pętli. Serwer może sprawdzić, czy próba powtórzenia się nie powiodła, i przerwać z błędem, gdy tak się stanie, aby użytkownik nie czekał na zawsze.

+0

Nie sądzę, że przekierowanie HTTP pozwala modyfikować parametry? Zauważ, że 307 musi działać dla dowolnej metody. Więc jeśli pierwotnym żądaniem był POST z 'form-data/multipart', nie sądzę, żebym mógł dodać parametr' retry'? – Jeroen

+0

Możesz przekierować do dowolnego adresu URL i może on zawierać parametry, więc dlaczego nie mogą różnić się od pierwotnych parametrów?Ale masz rację, że to nie zadziała w przypadku testu POST - nie spowoduje on ponownego wysłania formularza do nowego adresu URL. – Barmar

Powiązane problemy