😆

HTTPのステータスコード302, 303, 307の違い

2024/08/09に公開

HTTPのステータスコードのうち300番台はリダイレクトを意味します。

"301 Moved Permanently(恒久的リダイレクト)"などはわかりやすいのですが、

  • 302 Found(発見した)
  • 303 See Other(他を参照せよ)
  • 307 Temporary Redirect(一時的リダイレクト)

この3つは、よく似ていて使い分けが混乱しがちです。そこで、3者の使い分けをまとめました。

3つのリダイレクトの違い

実はリクエストがGET・HEADで行われた時は、レスポンスのステータスコードが302, 303, 307であっても、ブラウザの動作は変わりません。

ブラウザの動作に違いが生じるのは、リクエストがPOSTやPUT、DELETE、OPTIONSでリクエストされた時です。

302 Found(発見した)

過去の遺物となったステータスコードです。新しく作るWEBサイトでは使うべきではありません。

HTTP 1.0の規格では、302に対してブラウザは307相当の動作(リダイレクト先にも同じ動詞を使う)ことになっていました。

しかし、実際には多くのブラウザは303相当の動作(リダイレクト先にはGET)をしており、この規格外の仕様を前提にしたWEBサイトも存在していたため、今さらブラウザの仕様を訂正することもできません。

そこで、HTTP 1.1では303(実際のブラウザの仕様)と307(302の本来の動作)が定義されました。

"303 See Other(他を参照せよ)"

「リクエストされた処理を最初のURLで実際に行った。しかし、その結果はリダイレクト先からGETで取得して欲しい。」ことを表したい時に使います。

ブラウザは、最初のリクエストがPOSTであっても、リダイレクト先にはGETでリクエストします。

"307 Temporary Redirect(一時的リダイレクト)"

「リクエストされたURLでは実際の処理を行わなかった・別のURLに改めてリクエストして欲しい」という状況で使うべきステータスコードです。

ブラウザは、最初のリクエストがPOSTであれば、ブラウザはリダイレクト先にもPOSTでリクエストします。

つまり、"301 Moved Permanently(恒久的リダイレクト)"の「一時的版」であると思えばよいでしょう。

まとめ表

302 303 307
Reason Phrase Found See Other Temporary Redirect
本来=GET -> リダイレクト先に使うMethod? GET GET GET
本来=HEAD -> リダイレクト先に使うMethod? HEAD HEAD HEAD
本来=POST -> リダイレクト先に使うMethod? POST (多くの実装ではGET) GET POST

DELETE/PUT/OPTIONSもPOSTと同様。

RFCの説明

以下、日本語訳から抜粋します。各ステータスコードで共通する部分と、HTTP 1.1以前のブラウザに関する注意は省略しています。

302 Found

リクエストされたリソースは、一時的に別の URI に属している。(中略)

注意: RFC 1945 や RFC 2068 では、クライアントはリダイレクトするリクエストのメソッドを変えてはならないと明確に述べられている。
しかしながら、多くの既存ユーザエージェントは 302 レスポンスをまるで 303 レスポンスのようにみなし、元々のリクエストメソッドにかかわらず
Location フィールド値へと GET を行う。ステータスコード 303 と 307は、クライアントが期待する反応の種類を明確にしたいというサーバのために加えられた。
</blockquote>

303 See Other

リクエストに対するレスポンスは別の URI の元から発見でき、このリソース
を GET メソッドを使用して回収す べきである。このメソッドは、主に
POST によって活性化される {POST-activated} スクリプトの出力が選択され
たリソースへユーザエージェントをリダイレクトできるようにするために存
在する。新しい URI は元々リクエストされたリソースに対する代わりの参照
ではない。303 レスポンスはキャッシュ可能し てはならない が、二番目
の (リダイレクトされた) リクエストへのレスポンスはキャッシュ可能であ
る。
(以下略)

307 Temporary Redirect

リクエストされたリソースは、一時的に別の URI に属している。(以下略)

リンク

Discussion