web-dev-qa-db-ja.com

同じリクエストを再試行するためのHTTPステータスコード

クライアントに同じリクエストを再度実行するように指示するHTTPステータスコードはありますか?

リクエストを処理するときにサーバーがロックが消えるのを「待つ」必要がある状況に直面しています。ただし、ロックがなくなるまでに、リクエストはタイムアウト制限に近づく可能性があります。したがって、代わりに、ロックが解除されたら、クライアントに同じ要求をもう一度実行するように指示したいと思います。

私が思いついた最善の方法は、同じ場所へのHTTP 307ですが、一部のブラウザーはこれに同意しないかもしれません(リダイレクトループ検出)。

27
Jeroen

サーバーがリクエストを処理できない場合のcorrect応答は 503 Service Unavailable です。条件が一時的である場合、それはあなたの場合のように、 Retry-After ヘッダーを設定して、再試行するまでに待機する必要がある時間をクライアントに通知できます。

ただし、これによってブラウザがリクエストを再度実行する必要はありません。これは、JavaScriptで自分で処理する必要があるものです。たとえば、jqueryでajax POSTリクエストを再試行する方法を以下に示します。

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);
      }
    }
  });
}

上記のコードは、再試行遅延が秒単位で指定されているRetry-Afterヘッダーのみをサポートすることに注意してください。もう少し作業が必要な日付をサポートする場合。量産コードでは、永久に再試行を繰り返さないように、ある種のカウンターもお勧めします。

リクエストを自動的に繰り返すために307ステータスコードを使用することに関しては、それは良い考えではないと思います。ブラウザーのループ検出を回避するために再試行パラメーターを追加したとしても(これは恐ろしいハックのように感じられます)、POSTリクエストでは機能しません。From RFC2616

GETまたはHEAD以外のリクエストへの応答として307ステータスコードを受け取った場合、ユーザーエージェントは、ユーザーが確認できない限り、リクエストを自動的にリダイレクトしてはなりません(MUST NOT)。

一部のブラウザはこの要件を無視することが知られていますが、これは間違いなく正しくないため、信頼する必要はありません。

POSTリクエストを使用していない場合は、ほぼ確実に使用する必要があります。GETリクエスト 副作用がないはずです を忘れないでください。デフォルトでは、あなたの問題の説明から、あなたのリクエストが副作用のあることをしているように思われます。

31

307リダイレクトを使用しますが、再試行カウンターを追加します。

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

これにより、再試行ごとにURLが異なり、ループ検出が防止されます。そして、サーバーは再試行が制限に達したかどうかをチェックし、それが発生したときにエラーで中止できるので、ユーザーは永遠に待機しません。

3
Barmar