Rails 7.1 の Host Authorization 設定:テスト環境での 403 エラーの解決

※この記事はClaudeCodeを利用して実装した際にハマったことを、ClaudeCodeにブログ記事を書いてもらっています。

はじめに

Rails 7.1 でテストを実行していると、予期しない 403 Forbidden エラーが発生することがあります。特に Request specs や System specs で「Host Authorization」に関連するエラーが起きることがあります。本記事では、この問題の原因と解決方法を説明します。

問題の背景

Rails 7.1 では、セキュリティ強化の一環として Host Authorization という機能が導入されました。これはホスト名の検証を通じて HTTP Host ヘッダー攻撃を防ぐ機能です。

デフォルトでは、リクエストの Host ヘッダーが許可されたホスト名と一致しない場合、403 エラーが返されます。

テスト環境での設定

従来の方法(非推奨)

# config/environments/test.rb
config.hosts = nil

この設定で十分だと思われていましたが、Rails 7.1 ではこれだけでは不十分な場合があります。

推奨される方法

# config/environments/test.rb
config.hosts.clear
config.host_authorization = { exclude: ->(request) { true } }

この設定では:

  • config.hosts.clear でホスト許可リストをクリアする
  • config.host_authorization = { exclude: ... } で全てのリクエストを Host Authorization の対象外にする

複合的な設定が必要な理由

Rails 7.1 では config.hostsconfig.host_authorization が独立した設定になりました。

  • config.hosts のみを設定しても、Host Authorization チェック自体は実行されます
  • config.host_authorization でチェックを除外することで、初めて 403 エラーが回避されます

つまり、両方の設定が揃って初めてテスト環境での Host Authorization エラーが解決するのです。

実装例

Request specs での使用例

# spec/requests/admin/menus_spec.rb
describe 'Admin Menus API' do
  before do
    # Host Authorization が無効になるため、
    # localhost:3000 以外のホスト名でもリクエスト可能
    get '/admin/menus'
  end

  it 'should return menus' do
    expect(response).to have_http_status(:ok)
  end
end

System specs での使用例

# spec/system/orders_spec.rb
describe 'Order Flow' do
  it 'should display orders form' do
    # Host Authorization が無効になるため、
    # Capybara が使用するホスト名でも正常に動作
    visit new_order_path
    expect(page).to have_text 'ご注文をどうぞ'
  end
end

トラブルシューティング

まだ 403 エラーが出ている場合

  1. config/environments/test.rb が正しく読み込まれているか確認
   puts "RAILS_ENV: #{Rails.env}"  # 'test' と表示されることを確認
  1. サーバーを再起動
   docker-compose restart web
   rails server restart
  1. 複数の環境設定ファイルが存在する場合は、ローカル設定(test.local.rb)を確認

参考資料

まとめ

Rails 7.1 でテスト環境の Host Authorization エラーを解決するには、config.hosts.clearconfig.host_authorization = { exclude: ... } を組み合わせて設定することが必要です。単一の設定では不十分な場合があるため、両方を設定することが重要です。