rack-attack 6.1.0 → 6.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +11 -2
- data/lib/rack/attack.rb +136 -124
- data/lib/rack/attack/cache.rb +4 -1
- data/lib/rack/attack/check.rb +2 -1
- data/lib/rack/attack/path_normalizer.rb +20 -18
- data/lib/rack/attack/railtie.rb +21 -0
- data/lib/rack/attack/store_proxy/active_support_redis_store_proxy.rb +3 -1
- data/lib/rack/attack/store_proxy/mem_cache_store_proxy.rb +3 -1
- data/lib/rack/attack/store_proxy/redis_cache_store_proxy.rb +22 -6
- data/lib/rack/attack/throttle.rb +3 -2
- data/lib/rack/attack/track.rb +6 -5
- data/lib/rack/attack/version.rb +1 -1
- data/spec/acceptance/rails_middleware_spec.rb +41 -0
- data/spec/acceptance/stores/active_support_mem_cache_store_pooled_spec.rb +1 -3
- data/spec/acceptance/stores/active_support_redis_cache_store_pooled_spec.rb +7 -1
- data/spec/acceptance/stores/active_support_redis_cache_store_spec.rb +6 -1
- data/spec/acceptance/stores/connection_pool_dalli_client_spec.rb +3 -3
- data/spec/allow2ban_spec.rb +17 -14
- data/spec/fail2ban_spec.rb +17 -16
- data/spec/rack_attack_instrumentation_spec.rb +1 -1
- data/spec/rack_attack_path_normalizer_spec.rb +2 -2
- data/spec/rack_attack_spec.rb +36 -13
- data/spec/rack_attack_throttle_spec.rb +12 -12
- data/spec/rack_attack_track_spec.rb +8 -5
- data/spec/spec_helper.rb +5 -4
- metadata +30 -21
@@ -15,17 +15,33 @@ module Rack
|
|
15
15
|
#
|
16
16
|
# So in order to workaround this we use RedisCacheStore#write (which sets expiration) to initialize
|
17
17
|
# the counter. After that we continue using the original RedisCacheStore#increment.
|
18
|
-
|
19
|
-
|
18
|
+
rescuing do
|
19
|
+
if options[:expires_in] && !read(name)
|
20
|
+
write(name, amount, options)
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
amount
|
23
|
+
else
|
24
|
+
super
|
25
|
+
end
|
24
26
|
end
|
25
27
|
end
|
26
28
|
|
29
|
+
def read(*_args)
|
30
|
+
rescuing { super }
|
31
|
+
end
|
32
|
+
|
27
33
|
def write(name, value, options = {})
|
28
|
-
|
34
|
+
rescuing do
|
35
|
+
super(name, value, options.merge!(raw: true))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def rescuing
|
42
|
+
yield
|
43
|
+
rescue Redis::BaseError
|
44
|
+
nil
|
29
45
|
end
|
30
46
|
end
|
31
47
|
end
|
data/lib/rack/attack/throttle.rb
CHANGED
@@ -7,11 +7,12 @@ module Rack
|
|
7
7
|
|
8
8
|
attr_reader :name, :limit, :period, :block, :type
|
9
9
|
def initialize(name, options, &block)
|
10
|
-
@name
|
10
|
+
@name = name
|
11
|
+
@block = block
|
11
12
|
MANDATORY_OPTIONS.each do |opt|
|
12
13
|
raise ArgumentError, "Must pass #{opt.inspect} option" unless options[opt]
|
13
14
|
end
|
14
|
-
@limit
|
15
|
+
@limit = options[:limit]
|
15
16
|
@period = options[:period].respond_to?(:call) ? options[:period] : options[:period].to_i
|
16
17
|
@type = options.fetch(:type, :throttle)
|
17
18
|
end
|
data/lib/rack/attack/track.rb
CHANGED
@@ -8,11 +8,12 @@ module Rack
|
|
8
8
|
def initialize(name, options = {}, &block)
|
9
9
|
options[:type] = :track
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
@filter =
|
12
|
+
if options[:limit] && options[:period]
|
13
|
+
Throttle.new(name, options, &block)
|
14
|
+
else
|
15
|
+
Check.new(name, options, &block)
|
16
|
+
end
|
16
17
|
end
|
17
18
|
|
18
19
|
def matched_by?(request)
|
data/lib/rack/attack/version.rb
CHANGED
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../spec_helper"
|
4
|
+
|
5
|
+
if defined?(Rails)
|
6
|
+
describe "Middleware for Rails" do
|
7
|
+
before do
|
8
|
+
@app = Class.new(Rails::Application) do
|
9
|
+
config.eager_load = false
|
10
|
+
config.logger = Logger.new(nil) # avoid creating the log/ directory automatically
|
11
|
+
config.cache_store = :null_store # avoid creating tmp/ directory for cache
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
if Gem::Version.new(Rails::VERSION::STRING) >= Gem::Version.new("5.1")
|
16
|
+
it "is used by default" do
|
17
|
+
@app.initialize!
|
18
|
+
assert_equal 1, @app.middleware.count(Rack::Attack)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "is not added when it was added explicitly" do
|
22
|
+
@app.config.middleware.use(Rack::Attack)
|
23
|
+
@app.initialize!
|
24
|
+
assert_equal 1, @app.middleware.count(Rack::Attack)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "is not added when it was explicitly deleted" do
|
28
|
+
@app.config.middleware.delete(Rack::Attack)
|
29
|
+
@app.initialize!
|
30
|
+
refute @app.middleware.include?(Rack::Attack)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
if Gem::Version.new(Rails::VERSION::STRING) < Gem::Version.new("5.1")
|
35
|
+
it "is not used by default" do
|
36
|
+
@app.initialize!
|
37
|
+
assert_equal 0, @app.middleware.count(Rack::Attack)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -15,8 +15,6 @@ if defined?(::ConnectionPool) && defined?(::Dalli)
|
|
15
15
|
Rack::Attack.cache.store.clear
|
16
16
|
end
|
17
17
|
|
18
|
-
it_works_for_cache_backed_features(fetch_from_store: ->(key) {
|
19
|
-
Rack::Attack.cache.store.read(key)
|
20
|
-
})
|
18
|
+
it_works_for_cache_backed_features(fetch_from_store: ->(key) { Rack::Attack.cache.store.read(key) })
|
21
19
|
end
|
22
20
|
end
|
@@ -2,7 +2,13 @@
|
|
2
2
|
|
3
3
|
require_relative "../../spec_helper"
|
4
4
|
|
5
|
-
|
5
|
+
should_run =
|
6
|
+
defined?(::ConnectionPool) &&
|
7
|
+
defined?(::Redis) &&
|
8
|
+
Gem::Version.new(::Redis::VERSION) >= Gem::Version.new("4") &&
|
9
|
+
defined?(::ActiveSupport::Cache::RedisCacheStore)
|
10
|
+
|
11
|
+
if should_run
|
6
12
|
require_relative "../../support/cache_store_helper"
|
7
13
|
require "timecop"
|
8
14
|
|
@@ -2,7 +2,12 @@
|
|
2
2
|
|
3
3
|
require_relative "../../spec_helper"
|
4
4
|
|
5
|
-
|
5
|
+
should_run =
|
6
|
+
defined?(::Redis) &&
|
7
|
+
Gem::Version.new(::Redis::VERSION) >= Gem::Version.new("4") &&
|
8
|
+
defined?(::ActiveSupport::Cache::RedisCacheStore)
|
9
|
+
|
10
|
+
if should_run
|
6
11
|
require_relative "../../support/cache_store_helper"
|
7
12
|
require "timecop"
|
8
13
|
|
@@ -17,8 +17,8 @@ if defined?(::Dalli) && defined?(::ConnectionPool)
|
|
17
17
|
Rack::Attack.cache.store.with { |client| client.flush_all }
|
18
18
|
end
|
19
19
|
|
20
|
-
it_works_for_cache_backed_features(
|
21
|
-
Rack::Attack.cache.store.with { |client| client.fetch(key) }
|
22
|
-
|
20
|
+
it_works_for_cache_backed_features(
|
21
|
+
fetch_from_store: ->(key) { Rack::Attack.cache.store.with { |client| client.fetch(key) } }
|
22
|
+
)
|
23
23
|
end
|
24
24
|
end
|
data/spec/allow2ban_spec.rb
CHANGED
@@ -20,7 +20,8 @@ describe 'Rack::Attack.Allow2Ban' do
|
|
20
20
|
describe 'making ok request' do
|
21
21
|
it 'succeeds' do
|
22
22
|
get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
|
23
|
-
|
23
|
+
|
24
|
+
_(last_response.status).must_equal 200
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
@@ -29,17 +30,18 @@ describe 'Rack::Attack.Allow2Ban' do
|
|
29
30
|
before { get '/?foo=OMGHAX', {}, 'REMOTE_ADDR' => '1.2.3.4' }
|
30
31
|
|
31
32
|
it 'succeeds' do
|
32
|
-
last_response.status.must_equal 200
|
33
|
+
_(last_response.status).must_equal 200
|
33
34
|
end
|
34
35
|
|
35
36
|
it 'increases fail count' do
|
36
37
|
key = "rack::attack:#{Time.now.to_i / @findtime}:allow2ban:count:1.2.3.4"
|
37
|
-
|
38
|
+
|
39
|
+
_(@cache.store.read(key)).must_equal 1
|
38
40
|
end
|
39
41
|
|
40
42
|
it 'is not banned' do
|
41
43
|
key = "rack::attack:allow2ban:1.2.3.4"
|
42
|
-
@cache.store.read(key).must_be_nil
|
44
|
+
_(@cache.store.read(key)).must_be_nil
|
43
45
|
end
|
44
46
|
end
|
45
47
|
|
@@ -51,17 +53,17 @@ describe 'Rack::Attack.Allow2Ban' do
|
|
51
53
|
end
|
52
54
|
|
53
55
|
it 'succeeds' do
|
54
|
-
last_response.status.must_equal 200
|
56
|
+
_(last_response.status).must_equal 200
|
55
57
|
end
|
56
58
|
|
57
59
|
it 'increases fail count' do
|
58
60
|
key = "rack::attack:#{Time.now.to_i / @findtime}:allow2ban:count:1.2.3.4"
|
59
|
-
@cache.store.read(key).must_equal 2
|
61
|
+
_(@cache.store.read(key)).must_equal 2
|
60
62
|
end
|
61
63
|
|
62
64
|
it 'is banned' do
|
63
65
|
key = "rack::attack:allow2ban:ban:1.2.3.4"
|
64
|
-
@cache.store.read(key).must_equal 1
|
66
|
+
_(@cache.store.read(key)).must_equal 1
|
65
67
|
end
|
66
68
|
end
|
67
69
|
end
|
@@ -77,7 +79,8 @@ describe 'Rack::Attack.Allow2Ban' do
|
|
77
79
|
describe 'making request for other discriminator' do
|
78
80
|
it 'succeeds' do
|
79
81
|
get '/', {}, 'REMOTE_ADDR' => '2.2.3.4'
|
80
|
-
|
82
|
+
|
83
|
+
_(last_response.status).must_equal 200
|
81
84
|
end
|
82
85
|
end
|
83
86
|
|
@@ -87,17 +90,17 @@ describe 'Rack::Attack.Allow2Ban' do
|
|
87
90
|
end
|
88
91
|
|
89
92
|
it 'fails' do
|
90
|
-
last_response.status.must_equal 403
|
93
|
+
_(last_response.status).must_equal 403
|
91
94
|
end
|
92
95
|
|
93
96
|
it 'does not increase fail count' do
|
94
97
|
key = "rack::attack:#{Time.now.to_i / @findtime}:allow2ban:count:1.2.3.4"
|
95
|
-
@cache.store.read(key).must_equal 2
|
98
|
+
_(@cache.store.read(key)).must_equal 2
|
96
99
|
end
|
97
100
|
|
98
101
|
it 'is still banned' do
|
99
102
|
key = "rack::attack:allow2ban:ban:1.2.3.4"
|
100
|
-
@cache.store.read(key).must_equal 1
|
103
|
+
_(@cache.store.read(key)).must_equal 1
|
101
104
|
end
|
102
105
|
end
|
103
106
|
|
@@ -107,17 +110,17 @@ describe 'Rack::Attack.Allow2Ban' do
|
|
107
110
|
end
|
108
111
|
|
109
112
|
it 'fails' do
|
110
|
-
last_response.status.must_equal 403
|
113
|
+
_(last_response.status).must_equal 403
|
111
114
|
end
|
112
115
|
|
113
116
|
it 'does not increase fail count' do
|
114
117
|
key = "rack::attack:#{Time.now.to_i / @findtime}:allow2ban:count:1.2.3.4"
|
115
|
-
@cache.store.read(key).must_equal 2
|
118
|
+
_(@cache.store.read(key)).must_equal 2
|
116
119
|
end
|
117
120
|
|
118
121
|
it 'is still banned' do
|
119
122
|
key = "rack::attack:allow2ban:ban:1.2.3.4"
|
120
|
-
@cache.store.read(key).must_equal 1
|
123
|
+
_(@cache.store.read(key)).must_equal 1
|
121
124
|
end
|
122
125
|
end
|
123
126
|
end
|
data/spec/fail2ban_spec.rb
CHANGED
@@ -20,7 +20,7 @@ describe 'Rack::Attack.Fail2Ban' do
|
|
20
20
|
describe 'making ok request' do
|
21
21
|
it 'succeeds' do
|
22
22
|
get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
|
23
|
-
last_response.status.must_equal 200
|
23
|
+
_(last_response.status).must_equal 200
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -29,17 +29,17 @@ describe 'Rack::Attack.Fail2Ban' do
|
|
29
29
|
before { get '/?foo=OMGHAX', {}, 'REMOTE_ADDR' => '1.2.3.4' }
|
30
30
|
|
31
31
|
it 'fails' do
|
32
|
-
last_response.status.must_equal 403
|
32
|
+
_(last_response.status).must_equal 403
|
33
33
|
end
|
34
34
|
|
35
35
|
it 'increases fail count' do
|
36
36
|
key = "rack::attack:#{Time.now.to_i / @findtime}:fail2ban:count:1.2.3.4"
|
37
|
-
@cache.store.read(key).must_equal 1
|
37
|
+
_(@cache.store.read(key)).must_equal 1
|
38
38
|
end
|
39
39
|
|
40
40
|
it 'is not banned' do
|
41
41
|
key = "rack::attack:fail2ban:1.2.3.4"
|
42
|
-
@cache.store.read(key).must_be_nil
|
42
|
+
_(@cache.store.read(key)).must_be_nil
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
@@ -51,17 +51,17 @@ describe 'Rack::Attack.Fail2Ban' do
|
|
51
51
|
end
|
52
52
|
|
53
53
|
it 'fails' do
|
54
|
-
last_response.status.must_equal 403
|
54
|
+
_(last_response.status).must_equal 403
|
55
55
|
end
|
56
56
|
|
57
57
|
it 'increases fail count' do
|
58
58
|
key = "rack::attack:#{Time.now.to_i / @findtime}:fail2ban:count:1.2.3.4"
|
59
|
-
@cache.store.read(key).must_equal 2
|
59
|
+
_(@cache.store.read(key)).must_equal 2
|
60
60
|
end
|
61
61
|
|
62
62
|
it 'is banned' do
|
63
63
|
key = "rack::attack:fail2ban:ban:1.2.3.4"
|
64
|
-
@cache.store.read(key).must_equal 1
|
64
|
+
_(@cache.store.read(key)).must_equal 1
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
@@ -73,7 +73,7 @@ describe 'Rack::Attack.Fail2Ban' do
|
|
73
73
|
end
|
74
74
|
|
75
75
|
it 'succeeds' do
|
76
|
-
last_response.status.must_equal 200
|
76
|
+
_(last_response.status).must_equal 200
|
77
77
|
end
|
78
78
|
|
79
79
|
it 'resets fail count' do
|
@@ -82,7 +82,7 @@ describe 'Rack::Attack.Fail2Ban' do
|
|
82
82
|
end
|
83
83
|
|
84
84
|
it 'IP is not banned' do
|
85
|
-
Rack::Attack::Fail2Ban.banned?('1.2.3.4').must_equal false
|
85
|
+
_(Rack::Attack::Fail2Ban.banned?('1.2.3.4')).must_equal false
|
86
86
|
end
|
87
87
|
end
|
88
88
|
end
|
@@ -98,7 +98,8 @@ describe 'Rack::Attack.Fail2Ban' do
|
|
98
98
|
describe 'making request for other discriminator' do
|
99
99
|
it 'succeeds' do
|
100
100
|
get '/', {}, 'REMOTE_ADDR' => '2.2.3.4'
|
101
|
-
|
101
|
+
|
102
|
+
_(last_response.status).must_equal 200
|
102
103
|
end
|
103
104
|
end
|
104
105
|
|
@@ -108,17 +109,17 @@ describe 'Rack::Attack.Fail2Ban' do
|
|
108
109
|
end
|
109
110
|
|
110
111
|
it 'fails' do
|
111
|
-
last_response.status.must_equal 403
|
112
|
+
_(last_response.status).must_equal 403
|
112
113
|
end
|
113
114
|
|
114
115
|
it 'does not increase fail count' do
|
115
116
|
key = "rack::attack:#{Time.now.to_i / @findtime}:fail2ban:count:1.2.3.4"
|
116
|
-
@cache.store.read(key).must_equal 2
|
117
|
+
_(@cache.store.read(key)).must_equal 2
|
117
118
|
end
|
118
119
|
|
119
120
|
it 'is still banned' do
|
120
121
|
key = "rack::attack:fail2ban:ban:1.2.3.4"
|
121
|
-
@cache.store.read(key).must_equal 1
|
122
|
+
_(@cache.store.read(key)).must_equal 1
|
122
123
|
end
|
123
124
|
end
|
124
125
|
|
@@ -128,17 +129,17 @@ describe 'Rack::Attack.Fail2Ban' do
|
|
128
129
|
end
|
129
130
|
|
130
131
|
it 'fails' do
|
131
|
-
last_response.status.must_equal 403
|
132
|
+
_(last_response.status).must_equal 403
|
132
133
|
end
|
133
134
|
|
134
135
|
it 'does not increase fail count' do
|
135
136
|
key = "rack::attack:#{Time.now.to_i / @findtime}:fail2ban:count:1.2.3.4"
|
136
|
-
@cache.store.read(key).must_equal 2
|
137
|
+
_(@cache.store.read(key)).must_equal 2
|
137
138
|
end
|
138
139
|
|
139
140
|
it 'is still banned' do
|
140
141
|
key = "rack::attack:fail2ban:ban:1.2.3.4"
|
141
|
-
@cache.store.read(key).must_equal 1
|
142
|
+
_(@cache.store.read(key)).must_equal 1
|
142
143
|
end
|
143
144
|
end
|
144
145
|
end
|
@@ -6,14 +6,14 @@ describe Rack::Attack::PathNormalizer do
|
|
6
6
|
subject { Rack::Attack::PathNormalizer }
|
7
7
|
|
8
8
|
it 'should have a normalize_path method' do
|
9
|
-
subject.normalize_path('/foo').must_equal '/foo'
|
9
|
+
_(subject.normalize_path('/foo')).must_equal '/foo'
|
10
10
|
end
|
11
11
|
|
12
12
|
describe 'FallbackNormalizer' do
|
13
13
|
subject { Rack::Attack::FallbackPathNormalizer }
|
14
14
|
|
15
15
|
it '#normalize_path does not change the path' do
|
16
|
-
subject.normalize_path('').must_equal ''
|
16
|
+
_(subject.normalize_path('')).must_equal ''
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
data/spec/rack_attack_spec.rb
CHANGED
@@ -12,7 +12,7 @@ describe 'Rack::Attack' do
|
|
12
12
|
|
13
13
|
it 'blocks requests with trailing slash' do
|
14
14
|
get '/foo/'
|
15
|
-
last_response.status.must_equal 403
|
15
|
+
_(last_response.status).must_equal 403
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
@@ -22,21 +22,21 @@ describe 'Rack::Attack' do
|
|
22
22
|
Rack::Attack.blocklist("ip #{@bad_ip}") { |req| req.ip == @bad_ip }
|
23
23
|
end
|
24
24
|
|
25
|
-
it
|
26
|
-
Rack::Attack.blocklists.key?("ip #{@bad_ip}").must_equal true
|
27
|
-
|
25
|
+
it 'has a blocklist' do
|
26
|
+
_(Rack::Attack.blocklists.key?("ip #{@bad_ip}")).must_equal true
|
27
|
+
end
|
28
28
|
|
29
29
|
describe "a bad request" do
|
30
30
|
before { get '/', {}, 'REMOTE_ADDR' => @bad_ip }
|
31
31
|
|
32
32
|
it "should return a blocklist response" do
|
33
|
-
last_response.status.must_equal 403
|
34
|
-
last_response.body.must_equal "Forbidden\n"
|
33
|
+
_(last_response.status).must_equal 403
|
34
|
+
_(last_response.body).must_equal "Forbidden\n"
|
35
35
|
end
|
36
36
|
|
37
37
|
it "should tag the env" do
|
38
|
-
last_request.env['rack.attack.matched'].must_equal "ip #{@bad_ip}"
|
39
|
-
last_request.env['rack.attack.match_type'].must_equal :blocklist
|
38
|
+
_(last_request.env['rack.attack.matched']).must_equal "ip #{@bad_ip}"
|
39
|
+
_(last_request.env['rack.attack.match_type']).must_equal :blocklist
|
40
40
|
end
|
41
41
|
|
42
42
|
it_allows_ok_requests
|
@@ -54,25 +54,48 @@ describe 'Rack::Attack' do
|
|
54
54
|
before { get '/', {}, 'REMOTE_ADDR' => @bad_ip, 'HTTP_USER_AGENT' => @good_ua }
|
55
55
|
|
56
56
|
it "should allow safelists before blocklists" do
|
57
|
-
last_response.status.must_equal 200
|
57
|
+
_(last_response.status).must_equal 200
|
58
58
|
end
|
59
59
|
|
60
60
|
it "should tag the env" do
|
61
|
-
last_request.env['rack.attack.matched'].must_equal 'good ua'
|
62
|
-
last_request.env['rack.attack.match_type'].must_equal :safelist
|
61
|
+
_(last_request.env['rack.attack.matched']).must_equal 'good ua'
|
62
|
+
_(last_request.env['rack.attack.match_type']).must_equal :safelist
|
63
63
|
end
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
67
|
describe '#blocklisted_response' do
|
68
68
|
it 'should exist' do
|
69
|
-
Rack::Attack.blocklisted_response.must_respond_to :call
|
69
|
+
_(Rack::Attack.blocklisted_response).must_respond_to :call
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
73
|
describe '#throttled_response' do
|
74
74
|
it 'should exist' do
|
75
|
-
Rack::Attack.throttled_response.must_respond_to :call
|
75
|
+
_(Rack::Attack.throttled_response).must_respond_to :call
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe 'enabled' do
|
81
|
+
it 'should be enabled by default' do
|
82
|
+
_(Rack::Attack.enabled).must_equal true
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should directly pass request when disabled' do
|
86
|
+
bad_ip = '1.2.3.4'
|
87
|
+
Rack::Attack.blocklist("ip #{bad_ip}") { |req| req.ip == bad_ip }
|
88
|
+
|
89
|
+
get '/', {}, 'REMOTE_ADDR' => bad_ip
|
90
|
+
_(last_response.status).must_equal 403
|
91
|
+
|
92
|
+
prev_enabled = Rack::Attack.enabled
|
93
|
+
begin
|
94
|
+
Rack::Attack.enabled = false
|
95
|
+
get '/', {}, 'REMOTE_ADDR' => bad_ip
|
96
|
+
_(last_response.status).must_equal 200
|
97
|
+
ensure
|
98
|
+
Rack::Attack.enabled = prev_enabled
|
76
99
|
end
|
77
100
|
end
|
78
101
|
end
|