diff --git a/README.md b/README.md index 538a732..7e68f89 100644 --- a/README.md +++ b/README.md @@ -68,12 +68,10 @@ Or install it yourself as: Then tell your ruby web application to use rack-attack as a middleware. -a) For __rails__ applications: +a) For __rails__ applications it is used by default. You can disable it permanently (like for specific environment) or temporarily (can be useful for specific test cases) by writing: ```ruby -# In config/application.rb - -config.middleware.use Rack::Attack +Rack::Attack.enabled = false ``` b) For __rack__ applications: diff --git a/lib/rack/attack.rb b/lib/rack/attack.rb index f4297a5..e38b4ba 100644 --- a/lib/rack/attack.rb +++ b/lib/rack/attack.rb @@ -6,6 +6,8 @@ require 'rack/attack/path_normalizer' require 'rack/attack/request' require "ipaddr" +require 'rack/attack/railtie' if defined?(Rails) + module Rack class Attack class MisconfiguredStoreError < StandardError; end @@ -28,7 +30,8 @@ module Rack autoload :Allow2Ban, 'rack/attack/allow2ban' class << self - attr_accessor :notifier, :blocklisted_response, :throttled_response, :anonymous_blocklists, :anonymous_safelists + attr_accessor :enabled, :notifier, :blocklisted_response, :throttled_response, + :anonymous_blocklists, :anonymous_safelists def safelist(name = nil, &block) safelist = Safelist.new(name, &block) @@ -134,6 +137,7 @@ module Rack end # Set defaults + @enabled = true @anonymous_blocklists = [] @anonymous_safelists = [] @notifier = ActiveSupport::Notifications if defined?(ActiveSupport::Notifications) @@ -148,6 +152,8 @@ module Rack end def call(env) + return @app.call(env) unless self.class.enabled + env['PATH_INFO'] = PathNormalizer.normalize_path(env['PATH_INFO']) request = Rack::Attack::Request.new(env) diff --git a/lib/rack/attack/railtie.rb b/lib/rack/attack/railtie.rb new file mode 100644 index 0000000..5136560 --- /dev/null +++ b/lib/rack/attack/railtie.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module Rack + class Attack + class Railtie < Rails::Railtie + config.after_initialize do |app| + include_middleware = app.middleware.none? { |m| m == Rack::Attack } + app.middleware.use(Rack::Attack) if include_middleware + end + end + end +end diff --git a/spec/rack_attack_spec.rb b/spec/rack_attack_spec.rb index 51d7cf4..83c3708 100644 --- a/spec/rack_attack_spec.rb +++ b/spec/rack_attack_spec.rb @@ -76,4 +76,27 @@ describe 'Rack::Attack' do end end end + + describe 'enabled' do + it 'should be enabled by default' do + Rack::Attack.enabled.must_equal true + end + + it 'should directly pass request when disabled' do + bad_ip = '1.2.3.4' + Rack::Attack.blocklist("ip #{bad_ip}") { |req| req.ip == bad_ip } + + get '/', {}, 'REMOTE_ADDR' => bad_ip + last_response.status.must_equal 403 + + prev_enabled = Rack::Attack.enabled + begin + Rack::Attack.enabled = false + get '/', {}, 'REMOTE_ADDR' => bad_ip + last_response.status.must_equal 200 + ensure + Rack::Attack.enabled = prev_enabled + end + end + end end