`request.safe_method?` と `request.unsafe_method?` の追加
ActionDispatch::Request に RFC 9110 §9.2.1 の命名規則に基づく safe_method? と unsafe_method? の2つの述語メソッドが追加されました。これにより、コントローラやミドルウェアでリクエストの安全性を判定する際、標準的な語彙でコードを記述できるようになります。
背景
コントローラやミドルウェアでは「このリクエストはサーバー状態を変更しうるか」という判定が頻繁に必要になります。しかし、これまで Rails にはその判定を一言で表す標準的なメソッドがなく、get? || head? のような ad-hoc な条件式が各コールサイトに散在していました。
HTTP の仕様書である RFC 9110 §9.2.1 は、GET・HEAD・OPTIONS・TRACE を「安全なメソッド(safe methods)」と定義しています。本 PR はこの仕様の命名をそのまま Rails のインターフェースに取り込むことで、意図を明示した共通の語彙を提供します。
コードベース全体で get? || head? のような表現を統一する語彙を持つことは、レビュー時の可読性向上とバグの防止につながります。たとえば OPTIONS や TRACE を見落とした不完全な条件式も、safe_method? に置き換えることで正確な判定ができます。
技術的な変更
actionpack/lib/action_dispatch/http/request.rb の bearer_token メソッドの直後に、2つのメソッドが追加されました。
# True if the request method is safe per RFC 9110 §9.2.1
# (GET, HEAD, OPTIONS, or TRACE).
def safe_method?
get? || head? || options? || trace?
end
# True if the request method may modify resources. Inverse of #safe_method?.
def unsafe_method?
!safe_method?
end
safe_method? は GET・HEAD・OPTIONS・TRACE の4メソッドを安全とみなし、既存の述語メソッドを組み合わせて実装されています。unsafe_method? はその単純な否定であり、POST・PUT・PATCH・DELETE などに対して true を返します。
テストは actionpack/test/dispatch/request_test.rb に RequestSafety クラスとして追加されており、安全なメソッド群と安全でないメソッド群のそれぞれで両メソッドの真偽値を検証しています。
class RequestSafety < BaseRequestTest
%w[GET HEAD OPTIONS TRACE].each do |method|
test "#{method} is a safe method" do
request = stub_request("REQUEST_METHOD" => method)
assert_predicate request, :safe_method?
assert_not_predicate request, :unsafe_method?
end
end
%w[POST PUT PATCH DELETE].each do |method|
test "#{method} is an unsafe method" do
request = stub_request("REQUEST_METHOD" => method)
assert_not_predicate request, :safe_method?
assert_predicate request, :unsafe_method?
end
end
end
設計判断
既存の述語メソッドへの委譲という最小限の実装が選ばれました。get? や head? といった個別の述語メソッドはすでに ActionDispatch::Request に存在しており、safe_method? はそれらを組み合わせるだけです。新たな HTTP メソッド判定ロジックを持たないため、既存の動作に影響を与えません。
unsafe_method? を !safe_method? として実装することで、安全性の定義が safe_method? に一元化されています。将来的に安全なメソッドの定義を変更する場合も、safe_method? の1か所を修正するだけで両メソッドの動作が一貫して更新されます。
また、仕様書の節番号(RFC 9110 §9.2.1)をコメントに明記することで、実装の根拠を追跡可能にしています。これは Rails の標準的なコーディングスタイルへの準拠であるとともに、将来の保守担当者への情報提供でもあります。
まとめ
本 PR は小規模ながら、HTTP 仕様の語彙を Rails のインターフェースに直接反映させた変更です。safe_method? / unsafe_method? を使うことで、各コールサイトに散在していた get? || head? パターンが標準化された一語で置き換えられ、仕様に忠実で読みやすいコードを書きやすくなります。