HTTPにPOSTリダイレクトがないのはなぜですか?


162

HTTPリダイレクトは、HTTPコード301および302(他のコードも可能)と、新しい場所の住所を持つ「ロケーション」として知られるヘッダーフィールドを介して行われます。ただし、ブラウザは常にそのURLに「GET」リクエストを送信します。

ただし、多くの場合、POSTを介してユーザーを別のドメインにリダイレクトする必要があります(銀行支払いなど)。これは一般的なシナリオであり、実際には要件です。HTTP仕様でこのような一般的な要件が無視されている理由を知っている人はいますか?回避策は、アクションをターゲットの場所(Locationヘッダーフィールドの値)に設定したフォーム(非表示フィールドのパラメーター付き)setTimeoutを送信し、それを使用してフォームをターゲットの場所に送信することです。


1
ステータスコード307は探していますか?以下の私の答えをご覧ください。
デイビッドRuttka

回答:


180

HTTP 1.1では、同じメソッドを使用してリクエストを繰り返し、データを送信する必要があることを示すステータスコード307)が実際にあります

他の人が言ったように、ここで誤用の可能性があり、それが多くのフレームワークが抽象化で301と302に固執する理由かもしれません。ただし、適切な理解と責任ある使用法により、探しているものを達成できるはずです。

ことに留意されたいW3.org仕様場合、METHODではないHEAD、またはGETユーザエージェントがユーザを促すべき新しい位置で再実行要求の前に。また古いユーザーエージェントが307で何をすべきかわからない場合に備えて、ユーザーにメモとフォールバックメカニズム提供する必要があります

このフォームの使用:

<form action="Test307.aspx" method="post">
    <input type="hidden" name="test" value="the test" />
    <input type="submit" value="test" />    
</form>

また、Test307.aspxにLocation:http : //google.com、Chrome 13およびFiddler を指定して307を返すだけで、「test = the test」が実際にGoogleに投稿されたことを確認できます。もちろん、GoogleはPOSTを許可していないため、それ以上の応答は405です。しかし、それはメカニズムを示しています。

詳細については、HTTPステータスコードのリストW3.org仕様を参照してください。

307一時的なリダイレクト(HTTP / 1.1以降)この場合、リクエストは別のURIで繰り返される必要がありますが、今後のリクエストでは元のURIを使用できます。2 303とは対照的に、元のリクエストを再発行する場合、リクエストメソッドを変更しないでください。たとえば、別のPOST要求を使用してPOST要求を繰り返す必要があります。


2
@DavidRuttka、ブラウザのサポート何ですか?
Pacerier

5
@DavidRuttkaは、rfc7231を考慮に入れるために回答を更新することをお勧めします(廃止rfc2616)。ユーザーへのプロンプトはrfc2616の要件に基づいています。この要件はrfc7231で削除され、rfc7231では307リダイレクトが要求メソッドを変更してはならないという要件も導入されています(引用文で回答の終わりに言及しています)。
nibarius

tools.ietf.org/id/draft-hunt-http-rest-redirect-00.htmlによれば、「HTTPリダイレクトコード301-306は、サービスプロバイダーがクライアントが実際にユーザーであることを認識していない限り使用しないでください」エージェント」ですので、ReSTfulサービスは301ではなく308を使用する必要があります。ただし、これはドラフトにすぎません。
ブルースアダムス

49

ここでこのページの良い説明を見つけました。

WWWで最も単純な状況は、「べき等」トランザクション、つまり、害を及ぼすことなく繰り返すことができるトランザクションです。これらは、単純なURL参照(HTMLのhref =またはsrc =属性など)の取得であるか、GETメソッドを使用したフォーム送信であるため、通常は「GET」トランザクションです。この種のトランザクションのリダイレクトは簡単で、質問はありません。クライアントは、新しいURLを指定するLocation:ヘッダーを含むリダイレクト応答を受信し、クライアントは新しいURLにトランザクションを再発行することでそれに応答します。これらのリダイレクトに関連付けられているさまざまな30xステータスコードには暗黙のキャッシュ可能性に違いがありますが、GETリクエストへの応答では基本的に類似しています(301と302)。

POSTトランザクションは、原則として非pot等(ピザの注文、投票など)であると定義されており、任意に繰り返すことはできません。

HTTPプロトコル仕様は、この区別を考慮するように設計されています。GETメソッドは本質的にべき等であると定義されていますが、POSTメソッドは、少なくとも潜在的に非べき等であると定義されています。仕様では、ユーザーが意図していないPOSTトランザクションを不注意に(再)送信したり、望まないコンテキストにPOSTを送信したりすることからユーザーを保護するために、クライアントエージェント(ブラウザーなど)が講じるいくつかの予防措置を求めています。

私は、ユーザーが望ましくない騒乱を引き起こしたり、アプリケーションに望ましくない損害を与えたりするのを防ぐために、技術的にユーザーを制限することは好きではありませんが、その点は理解でき、理にかなっています。


理由の多くは、インターチューブが遅く信頼性の低い時代(それはまだ世界の多くの場所にある)にまで及びます。私はダイヤルアップを使用したときをはっきりと覚えており、誰かが電話を拾うたびにランダムに切断されました。ページをリロードしてサーバーの状態を確認する方が、再送信して同じアクションを2回実行するリスクを負うよりも優れていました。
zzzzBov

@Falcon、「訪問者カウンター」を増やすことは、べき等でないと考えられますか?その場合は、ほとんどありませんウェブサイトのこれらの日は、冪等は... GETを行う
Pacerier

@Pacerier:通常、べき等は「意味のある方法でべき等」と解釈されます。たとえば、2回の訪問を記録するのではなく、同じアイテムを2回購入します。そうでなければ、あなたはまったく正しいでしょう。しかし実際には、仕様では、重複を防ぐためにページにIDを埋め込むなど、必要に応じてサーバーに意味のあるべき等dem性を要求する必要がありました。とにかく、POSTのリダイレクトを防止してもi等性は影響を受けません。これは、リクエストのターゲットが実際にそこにあることを示すメッセージです。
ローレンスドル

私はこれがこの推論のためにどのように理にかなっているのかわかりません。私がチェース銀行のウェブサイトにいて、フォームを送信するとします。私はすでにそれらに同意/信頼しています。そのデータを別のページにリダイレクトする必要がある場合、なぜ再度同意する必要があるのでしょうか。または別の例として、私はデフォルトでJavaScriptをオフにしている人だとしましょう。ある日、オンラインで住宅ローンのアプリに記入し、フォームを送信するとエラーが発生します。アプリが(POSTを使用して)データを事前入力するために記入したページにリダイレクトできると便利です。
-b01

@Flacon、リダイレクトをPOSTで制限することであらゆる面で混乱を防ぐことができるという証拠が必要です。私は最初に自分のデータでアプリを信頼する必要があるため、データを取得すると、アプリで何でもできるようになります。そして、リダイレクトはPOSTでのリクエストよりも脆弱だとは思いません。
b01

3

GET(および他のいくつかのメソッド)は、http仕様(RFC 2616)で「SAFE」として定義されています

9.1.1安全な方法

実装者は、ソフトウェアがインターネット上での対話におけるユーザーを表していることを認識し、ユーザーが自分自身や他の人にとって予期しない意味を持つ可能性のあるアクションを認識できるように注意する必要があります。

特に、GETメソッドとHEADメソッドには、取得以外のアクションを実行する重要性がないという慣習が確立されています。これらの方法は「安全」と見なされるべきです。これにより、ユーザーエージェントは、POST、PUT、DELETEなどの他のメソッドを特別な方法で表すことができるため、ユーザーは安全でない可能性のあるアクションが要求されているという事実を認識できます。

当然、サーバーがGET要求の実行の結果として副作用を生成しないことを保証することはできません。実際、一部の動的リソースはそれを機能と見なしています。ここでの重要な違いは、ユーザーが副作用を要求しなかったため、副作用を説明できないことです。

つまり、GETリクエストは、ユーザーが見たくないものを見る以外に、ユーザーに深刻な影響を与えることはありませんが、POSTリクエストは、ユーザーまたは他の人にとって重要なリソースを変更する可能性があります。

これはJavaScriptによって変更されましたが、従来はさまざまなユーザーインターフェイスがありました。ユーザーはリンクをクリックしてGETリクエストをトリガーできましたが、POSTリクエストをトリガーするにはフォームに入力する必要がありました。HTTPの設計者は、安全なメソッドと安全でないメソッドの区別を維持することに熱心だったと思います。

また、POSTにリダイレクトする必要はないと思います。実行する必要のあるアクションは、おそらくサーバー側コード内の関数を呼び出すことによって実行できます。または、別のサーバーで実行する必要がある場合は、ブラウザーがPOSTするURLを含むリダイレクトを送信する代わりに、サーバーそのサーバー自体にリクエストを行い、ユーザーのプロキシのように振る舞うことができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.