LoginSignup
0
0

Rack::Attackでのリクエスト制限時の問題と解決策

Posted at

背景

Railsアプリケーションにおいて、Rack::Attackを使用して特定のリクエストに制限を設けた際に、以下のエラーメッセージが発生しました。

NoMethodError at /reservations/confirm
undefined method `env' for {:request=>#<Rack::Attack::Request:0x00007fd2b4b8c3b8 @params=nil, @env={...}}>

このエラーは、Rack::Attack内のイベント購読の部分で発生しており、ペイロードから直接 env を呼び出そうとしたために発生しました。

問題点の特定

問題のコードは以下の部分です。

config/initializers/rack_attack.rb
  ActiveSupport::Notifications.subscribe('rack.attack') do |name, start, finish, request_id, req|
    Rails.logger.info "Rack::Attack: #{req.env['rack.attack.match_type']} from #{req.ip} blocked."
  end

または

config/initializers/rack_attack.rb
ActiveSupport::Notifications.subscribe('rack.attack') do |name, start, finish, request_id, payload|
  Rails.logger.info "Rack::Attack: #{payload[:request].env['rack.attack.match_type']} from #{payload[:request].ip} blocked."
end

などがエラーの原因になります。

解決策

payload[:request] が実際には Rack::Attack::Request オブジェクトであるため、.env を直接呼び出す必要があります。修正後のコードは以下のようになります。

ActiveSupport::Notifications.subscribe('rack.attack') do |name, start, finish, request_id, payload|
  Rails.logger.info "Rack::Attack: #{payload[:request].env['rack.attack.match_type']} from #{payload[:request].env['REMOTE_ADDR']} blocked."
end

おまけ: ユーザーフレンドリーな429エラーページの追加

リクエスト制限を超えた際に、ユーザーに対してより親切なフィードバックを提供するため、次のようなカスタム429エラーページを作成しました。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>リクエストが多すぎます</title>
    <style>
        body { font-family: "Helvetica Neue", Arial, sans-serif; line-height: 1.6; padding: 20px; }
        h1 { color: #ff6347; }
        p { max-width: 550px; }
    </style>
</head>
<body>
    <h1>お待ちください!</h1>
    <p>ただいまアクセスが集中しております。サーバーへの負担軽減のため、少し時間を置いてから再度お試しください。</p>
    <p>何度もこのメッセージが表示される場合は、サポートへお問い合わせください。</p>
</body>
</html>

このページは public/429.html として保存し、Rack::Attackの設定で指定することで、サーバーがリクエスト制限を行った際にこのページを表示するように設定しました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0