はじめに
こんにちは。アメリカで独学でエンジニアを目指している者です。
現在Railsチュートリアルを用いて勉強していますが、本日はそこで出てきたHTTPステータスコード 303 see_other について記事にしたいと思います
status: :see_other と HTTP 303 ステータスコード
はじめに
Rails でリダイレクト処理を行う場合、たとえば redirect_to root_url
といったコードをよく見かけるかと思います。ここに status: :see_other
オプションをつけることで、HTTP ステータスコード 303 を利用したリダイレクトが実現できます。本記事では、この status: :see_other
がどのような意味を持ち、なぜ使用されるのかを解説します。
303 (See Other) ステータスコードとは
HTTP には様々なステータスコードがありますが、その中で 303 は “See Other” と呼ばれています。これは以下のような特徴を持ちます。
-
リクエストメソッドを GET に変換する
- 元のリクエストが POST や DELETE などの非 GET リクエストであった場合、リダイレクト先には GET リクエストを送信するようにブラウザに指示します。
-
フォームの再送信を防ぐ
- POST や DELETE といった状態変更を伴うリクエストの直後にリダイレクトを挟むことで、ユーザーがブラウザを再読み込み (リロード) した際にもう一度同じリクエストを送ってしまう「二重送信」を防ぎます。
-
安全な再読み込みを実現
- ユーザーが戻る操作や再読み込みをしても、意図せず状態変更リクエスト (DELETE など) を行わずに済むようになります。
Rails での利用例
ログアウト処理 (DELETE → GET)
# SessionsController
class SessionsController < ApplicationController
# ...
def destroy
log_out
redirect_to root_url, status: :see_other
end
end
-
destroy
アクションは、多くの場合 HTTP メソッド DELETE に紐づけられています。 - Rails では、このアクションを呼び出した後に
redirect_to
を使ってトップページなどにリダイレクトすることが一般的です。 - ここで
status: :see_other
(ステータスコード 303) を指定すると、ブラウザは リダイレクト先へのリクエストを GET で行う よう指示されます。 - これにより、再読み込み時に DELETE リクエストが再度送られるのを防ぎ、安全なページ遷移が行えます。
なぜわざわざ 303 を使うのか?
通常のリダイレクトといえば、302 (Found) や 301 (Moved Permanently) なども使われることが多いですが、Rails ではあえて 303 を選択する利点があります。
-
PRG パターン (Post/Redirect/Get) のサポート
- フォーム送信による状態変更の直後に、別のページへリダイレクトするのは業界標準とも言える手法です。これによりユーザーが再読み込みした際に意図しない再送信を回避できます。
- 303 は PRG パターンに最適なステータスコードとして利用できます。
-
DELETE リクエストの二重送信を防ぐ
- ログアウト処理など、DELETE リクエストを伴う操作の後にページを再読み込みしても、再度 DELETE が行われず、安全な GET リクエストとなります。
-
明示的な意図を示す
- 303 は “See Other” という名前のとおり、あくまで「他のリソースを参照してね」とブラウザに伝えます。これは元のリクエストのメソッドをそのまま持ち越すような 307 (Temporary Redirect) とは異なり、明示的にメソッドを変えたいときに使われます。
まとめ
-
status: :see_other
を指定すると、HTTP 303 が使われ、ブラウザがリダイレクト先に GET でアクセスするようになります。 - 状態変更を伴うリクエスト (POST や DELETE) の後にリダイレクトを行う際、二重送信を防ぐために非常に便利です。
- Rails では特にセキュリティとユーザー体験を向上させるため、
status: :see_other
を積極的に活用するケースが見られます。
もし redirect_to some_path, status: :see_other
を見かけたら、「HTTP 303 を返すことでリダイレクト先では GET が行われ、再投稿や再ログアウトを防止するんだな」と理解していただければ幸いです。