※この記事は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.hosts と config.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 エラーが出ている場合
config/environments/test.rbが正しく読み込まれているか確認
puts "RAILS_ENV: #{Rails.env}" # 'test' と表示されることを確認
- サーバーを再起動
docker-compose restart web
rails server restart
- 複数の環境設定ファイルが存在する場合は、ローカル設定(
test.local.rb)を確認
参考資料
まとめ
Rails 7.1 でテスト環境の Host Authorization エラーを解決するには、config.hosts.clear と config.host_authorization = { exclude: ... } を組み合わせて設定することが必要です。単一の設定では不十分な場合があるため、両方を設定することが重要です。