rack-attack 5.4.0 → 6.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +78 -27
- data/Rakefile +3 -1
- data/bin/setup +8 -0
- data/lib/rack/attack.rb +137 -148
- data/lib/rack/attack/allow2ban.rb +2 -0
- data/lib/rack/attack/blocklist.rb +3 -1
- data/lib/rack/attack/cache.rb +9 -4
- data/lib/rack/attack/check.rb +5 -2
- data/lib/rack/attack/fail2ban.rb +2 -0
- data/lib/rack/attack/path_normalizer.rb +22 -18
- data/lib/rack/attack/railtie.rb +21 -0
- data/lib/rack/attack/request.rb +2 -0
- data/lib/rack/attack/safelist.rb +3 -1
- data/lib/rack/attack/store_proxy.rb +12 -24
- data/lib/rack/attack/store_proxy/active_support_redis_store_proxy.rb +39 -0
- data/lib/rack/attack/store_proxy/dalli_proxy.rb +27 -13
- data/lib/rack/attack/store_proxy/mem_cache_store_proxy.rb +21 -0
- data/lib/rack/attack/store_proxy/redis_cache_store_proxy.rb +23 -9
- data/lib/rack/attack/store_proxy/redis_proxy.rb +16 -10
- data/lib/rack/attack/store_proxy/redis_store_proxy.rb +5 -5
- data/lib/rack/attack/throttle.rb +12 -8
- data/lib/rack/attack/track.rb +9 -6
- data/lib/rack/attack/version.rb +3 -1
- data/spec/acceptance/allow2ban_spec.rb +2 -0
- data/spec/acceptance/blocking_ip_spec.rb +4 -2
- data/spec/acceptance/blocking_spec.rb +45 -3
- data/spec/acceptance/blocking_subnet_spec.rb +4 -2
- data/spec/acceptance/cache_store_config_for_allow2ban_spec.rb +50 -39
- data/spec/acceptance/cache_store_config_for_fail2ban_spec.rb +38 -29
- data/spec/acceptance/cache_store_config_for_throttle_spec.rb +2 -0
- data/spec/acceptance/cache_store_config_with_rails_spec.rb +2 -0
- data/spec/acceptance/customizing_blocked_response_spec.rb +2 -0
- data/spec/acceptance/customizing_throttled_response_spec.rb +2 -0
- data/spec/acceptance/extending_request_object_spec.rb +2 -0
- data/spec/acceptance/fail2ban_spec.rb +2 -0
- data/spec/acceptance/rails_middleware_spec.rb +41 -0
- data/spec/acceptance/safelisting_ip_spec.rb +4 -2
- data/spec/acceptance/safelisting_spec.rb +57 -3
- data/spec/acceptance/safelisting_subnet_spec.rb +4 -2
- data/spec/acceptance/stores/active_support_dalli_store_spec.rb +3 -23
- data/spec/acceptance/stores/active_support_mem_cache_store_pooled_spec.rb +20 -0
- data/spec/acceptance/stores/active_support_mem_cache_store_spec.rb +4 -24
- data/spec/acceptance/stores/active_support_memory_store_spec.rb +3 -23
- data/spec/acceptance/stores/active_support_redis_cache_store_pooled_spec.rb +10 -24
- data/spec/acceptance/stores/active_support_redis_cache_store_spec.rb +9 -25
- data/spec/acceptance/stores/active_support_redis_store_spec.rb +4 -24
- data/spec/acceptance/stores/connection_pool_dalli_client_spec.rb +5 -23
- data/spec/acceptance/stores/dalli_client_spec.rb +3 -23
- data/spec/acceptance/stores/redis_spec.rb +1 -23
- data/spec/acceptance/stores/redis_store_spec.rb +3 -23
- data/spec/acceptance/throttling_spec.rb +7 -5
- data/spec/acceptance/track_spec.rb +5 -3
- data/spec/acceptance/track_throttle_spec.rb +5 -3
- data/spec/allow2ban_spec.rb +20 -15
- data/spec/fail2ban_spec.rb +20 -17
- data/spec/integration/offline_spec.rb +3 -1
- data/spec/rack_attack_dalli_proxy_spec.rb +2 -0
- data/spec/rack_attack_instrumentation_spec.rb +42 -0
- data/spec/rack_attack_path_normalizer_spec.rb +4 -2
- data/spec/rack_attack_request_spec.rb +2 -0
- data/spec/rack_attack_spec.rb +38 -34
- data/spec/rack_attack_throttle_spec.rb +50 -19
- data/spec/rack_attack_track_spec.rb +12 -7
- data/spec/spec_helper.rb +10 -8
- data/spec/support/cache_store_helper.rb +27 -1
- metadata +48 -28
- data/lib/rack/attack/store_proxy/mem_cache_proxy.rb +0 -50
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_support/cache'
|
2
4
|
require_relative '../spec_helper'
|
3
5
|
|
@@ -22,7 +24,7 @@ if defined?(::ActiveSupport::Cache::RedisStore)
|
|
22
24
|
before do
|
23
25
|
@cache = Rack::Attack::Cache.new
|
24
26
|
# Use presumably unused port for Redis client
|
25
|
-
@cache.store = ActiveSupport::Cache::RedisStore.new(:
|
27
|
+
@cache.store = ActiveSupport::Cache::RedisStore.new(host: '127.0.0.1', port: 3333)
|
26
28
|
end
|
27
29
|
end
|
28
30
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "spec_helper"
|
4
|
+
|
5
|
+
# ActiveSupport::Subscribers added in ~> 4.0.2.0
|
6
|
+
if ActiveSupport::VERSION::MAJOR > 3
|
7
|
+
require_relative 'spec_helper'
|
8
|
+
require 'active_support/subscriber'
|
9
|
+
class CustomSubscriber < ActiveSupport::Subscriber
|
10
|
+
@notification_count = 0
|
11
|
+
|
12
|
+
class << self
|
13
|
+
attr_accessor :notification_count
|
14
|
+
end
|
15
|
+
|
16
|
+
def throttle(_event)
|
17
|
+
self.class.notification_count += 1
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'Rack::Attack.instrument' do
|
22
|
+
before do
|
23
|
+
@period = 60 # Use a long period; failures due to cache key rotation less likely
|
24
|
+
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
|
25
|
+
Rack::Attack.throttle('ip/sec', limit: 1, period: @period) { |req| req.ip }
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "with throttling" do
|
29
|
+
before do
|
30
|
+
ActiveSupport::Notifications.stub(:notifier, ActiveSupport::Notifications::Fanout.new) do
|
31
|
+
CustomSubscriber.attach_to("rack_attack")
|
32
|
+
2.times { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should instrument without error' do
|
37
|
+
_(last_response.status).must_equal 429
|
38
|
+
assert_equal 1, CustomSubscriber.notification_count
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -1,17 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'spec_helper'
|
2
4
|
|
3
5
|
describe Rack::Attack::PathNormalizer do
|
4
6
|
subject { Rack::Attack::PathNormalizer }
|
5
7
|
|
6
8
|
it 'should have a normalize_path method' do
|
7
|
-
subject.normalize_path('/foo').must_equal '/foo'
|
9
|
+
_(subject.normalize_path('/foo')).must_equal '/foo'
|
8
10
|
end
|
9
11
|
|
10
12
|
describe 'FallbackNormalizer' do
|
11
13
|
subject { Rack::Attack::FallbackPathNormalizer }
|
12
14
|
|
13
15
|
it '#normalize_path does not change the path' do
|
14
|
-
subject.normalize_path('').must_equal ''
|
16
|
+
_(subject.normalize_path('')).must_equal ''
|
15
17
|
end
|
16
18
|
end
|
17
19
|
end
|
data/spec/rack_attack_spec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'spec_helper'
|
2
4
|
|
3
5
|
describe 'Rack::Attack' do
|
@@ -10,7 +12,7 @@ describe 'Rack::Attack' do
|
|
10
12
|
|
11
13
|
it 'blocks requests with trailing slash' do
|
12
14
|
get '/foo/'
|
13
|
-
last_response.status.must_equal 403
|
15
|
+
_(last_response.status).must_equal 403
|
14
16
|
end
|
15
17
|
end
|
16
18
|
|
@@ -20,28 +22,21 @@ describe 'Rack::Attack' do
|
|
20
22
|
Rack::Attack.blocklist("ip #{@bad_ip}") { |req| req.ip == @bad_ip }
|
21
23
|
end
|
22
24
|
|
23
|
-
it
|
24
|
-
Rack::Attack.blocklists.key?("ip #{@bad_ip}").must_equal true
|
25
|
-
|
26
|
-
|
27
|
-
it('has a blacklist with a deprication warning') {
|
28
|
-
_, stderror = capture_io do
|
29
|
-
Rack::Attack.blacklists.key?("ip #{@bad_ip}").must_equal true
|
30
|
-
end
|
31
|
-
assert_match "[DEPRECATION] 'Rack::Attack.blacklists' is deprecated. Please use 'blocklists' instead.", stderror
|
32
|
-
}
|
25
|
+
it 'has a blocklist' do
|
26
|
+
_(Rack::Attack.blocklists.key?("ip #{@bad_ip}")).must_equal true
|
27
|
+
end
|
33
28
|
|
34
29
|
describe "a bad request" do
|
35
30
|
before { get '/', {}, 'REMOTE_ADDR' => @bad_ip }
|
36
31
|
|
37
32
|
it "should return a blocklist response" do
|
38
|
-
last_response.status.must_equal 403
|
39
|
-
last_response.body.must_equal "Forbidden\n"
|
33
|
+
_(last_response.status).must_equal 403
|
34
|
+
_(last_response.body).must_equal "Forbidden\n"
|
40
35
|
end
|
41
36
|
|
42
37
|
it "should tag the env" do
|
43
|
-
last_request.env['rack.attack.matched'].must_equal "ip #{@bad_ip}"
|
44
|
-
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
|
45
40
|
end
|
46
41
|
|
47
42
|
it_allows_ok_requests
|
@@ -55,43 +50,52 @@ describe 'Rack::Attack' do
|
|
55
50
|
|
56
51
|
it('has a safelist') { Rack::Attack.safelists.key?("good ua") }
|
57
52
|
|
58
|
-
it('has a whitelist with a deprication warning') {
|
59
|
-
_, stderror = capture_io do
|
60
|
-
Rack::Attack.whitelists.key?("good ua")
|
61
|
-
end
|
62
|
-
assert_match "[DEPRECATION] 'Rack::Attack.whitelists' is deprecated. Please use 'safelists' instead.", stderror
|
63
|
-
}
|
64
|
-
|
65
53
|
describe "with a request match both safelist & blocklist" do
|
66
54
|
before { get '/', {}, 'REMOTE_ADDR' => @bad_ip, 'HTTP_USER_AGENT' => @good_ua }
|
67
55
|
|
68
56
|
it "should allow safelists before blocklists" do
|
69
|
-
last_response.status.must_equal 200
|
57
|
+
_(last_response.status).must_equal 200
|
70
58
|
end
|
71
59
|
|
72
60
|
it "should tag the env" do
|
73
|
-
last_request.env['rack.attack.matched'].must_equal 'good ua'
|
74
|
-
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
|
75
63
|
end
|
76
64
|
end
|
77
65
|
end
|
78
66
|
|
79
67
|
describe '#blocklisted_response' do
|
80
68
|
it 'should exist' do
|
81
|
-
Rack::Attack.blocklisted_response.must_respond_to :call
|
82
|
-
end
|
83
|
-
|
84
|
-
it 'should give a deprication warning for blacklisted_response' do
|
85
|
-
_, stderror = capture_io do
|
86
|
-
Rack::Attack.blacklisted_response
|
87
|
-
end
|
88
|
-
assert_match "[DEPRECATION] 'Rack::Attack.blacklisted_response' is deprecated. Please use 'blocklisted_response' instead.", stderror
|
69
|
+
_(Rack::Attack.blocklisted_response).must_respond_to :call
|
89
70
|
end
|
90
71
|
end
|
91
72
|
|
92
73
|
describe '#throttled_response' do
|
93
74
|
it 'should exist' do
|
94
|
-
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
|
95
99
|
end
|
96
100
|
end
|
97
101
|
end
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'spec_helper'
|
2
4
|
|
3
5
|
describe 'Rack::Attack.throttle' do
|
4
6
|
before do
|
5
7
|
@period = 60 # Use a long period; failures due to cache key rotation less likely
|
6
8
|
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
|
7
|
-
Rack::Attack.throttle('ip/sec', :
|
9
|
+
Rack::Attack.throttle('ip/sec', limit: 1, period: @period) { |req| req.ip }
|
8
10
|
end
|
9
11
|
|
10
12
|
it('should have a throttle') { Rack::Attack.throttles.key?('ip/sec') }
|
@@ -16,12 +18,19 @@ describe 'Rack::Attack.throttle' do
|
|
16
18
|
|
17
19
|
it 'should set the counter for one request' do
|
18
20
|
key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4"
|
19
|
-
Rack::Attack.cache.store.read(key).must_equal 1
|
21
|
+
_(Rack::Attack.cache.store.read(key)).must_equal 1
|
20
22
|
end
|
21
23
|
|
22
24
|
it 'should populate throttle data' do
|
23
|
-
data = {
|
24
|
-
|
25
|
+
data = {
|
26
|
+
count: 1,
|
27
|
+
limit: 1,
|
28
|
+
period: @period,
|
29
|
+
epoch_time: Rack::Attack.cache.last_epoch_time.to_i,
|
30
|
+
discriminator: "1.2.3.4"
|
31
|
+
}
|
32
|
+
|
33
|
+
_(last_request.env['rack.attack.throttle_data']['ip/sec']).must_equal data
|
25
34
|
end
|
26
35
|
end
|
27
36
|
|
@@ -31,18 +40,26 @@ describe 'Rack::Attack.throttle' do
|
|
31
40
|
end
|
32
41
|
|
33
42
|
it 'should block the last request' do
|
34
|
-
last_response.status.must_equal 429
|
43
|
+
_(last_response.status).must_equal 429
|
35
44
|
end
|
36
45
|
|
37
46
|
it 'should tag the env' do
|
38
|
-
last_request.env['rack.attack.matched'].must_equal 'ip/sec'
|
39
|
-
last_request.env['rack.attack.match_type'].must_equal :throttle
|
40
|
-
|
41
|
-
last_request.env['rack.attack.
|
47
|
+
_(last_request.env['rack.attack.matched']).must_equal 'ip/sec'
|
48
|
+
_(last_request.env['rack.attack.match_type']).must_equal :throttle
|
49
|
+
|
50
|
+
_(last_request.env['rack.attack.match_data']).must_equal(
|
51
|
+
count: 2,
|
52
|
+
limit: 1,
|
53
|
+
period: @period,
|
54
|
+
epoch_time: Rack::Attack.cache.last_epoch_time.to_i,
|
55
|
+
discriminator: "1.2.3.4"
|
56
|
+
)
|
57
|
+
|
58
|
+
_(last_request.env['rack.attack.match_discriminator']).must_equal('1.2.3.4')
|
42
59
|
end
|
43
60
|
|
44
61
|
it 'should set a Retry-After header' do
|
45
|
-
last_response.headers['Retry-After'].must_equal @period.to_s
|
62
|
+
_(last_response.headers['Retry-After']).must_equal @period.to_s
|
46
63
|
end
|
47
64
|
end
|
48
65
|
end
|
@@ -51,7 +68,7 @@ describe 'Rack::Attack.throttle with limit as proc' do
|
|
51
68
|
before do
|
52
69
|
@period = 60 # Use a long period; failures due to cache key rotation less likely
|
53
70
|
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
|
54
|
-
Rack::Attack.throttle('ip/sec', :
|
71
|
+
Rack::Attack.throttle('ip/sec', limit: lambda { |_req| 1 }, period: @period) { |req| req.ip }
|
55
72
|
end
|
56
73
|
|
57
74
|
it_allows_ok_requests
|
@@ -61,12 +78,19 @@ describe 'Rack::Attack.throttle with limit as proc' do
|
|
61
78
|
|
62
79
|
it 'should set the counter for one request' do
|
63
80
|
key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4"
|
64
|
-
Rack::Attack.cache.store.read(key).must_equal 1
|
81
|
+
_(Rack::Attack.cache.store.read(key)).must_equal 1
|
65
82
|
end
|
66
83
|
|
67
84
|
it 'should populate throttle data' do
|
68
|
-
data = {
|
69
|
-
|
85
|
+
data = {
|
86
|
+
count: 1,
|
87
|
+
limit: 1,
|
88
|
+
period: @period,
|
89
|
+
epoch_time: Rack::Attack.cache.last_epoch_time.to_i,
|
90
|
+
discriminator: "1.2.3.4"
|
91
|
+
}
|
92
|
+
|
93
|
+
_(last_request.env['rack.attack.throttle_data']['ip/sec']).must_equal data
|
70
94
|
end
|
71
95
|
end
|
72
96
|
end
|
@@ -75,7 +99,7 @@ describe 'Rack::Attack.throttle with period as proc' do
|
|
75
99
|
before do
|
76
100
|
@period = 60 # Use a long period; failures due to cache key rotation less likely
|
77
101
|
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
|
78
|
-
Rack::Attack.throttle('ip/sec', :
|
102
|
+
Rack::Attack.throttle('ip/sec', limit: lambda { |_req| 1 }, period: lambda { |_req| @period }) { |req| req.ip }
|
79
103
|
end
|
80
104
|
|
81
105
|
it_allows_ok_requests
|
@@ -85,12 +109,19 @@ describe 'Rack::Attack.throttle with period as proc' do
|
|
85
109
|
|
86
110
|
it 'should set the counter for one request' do
|
87
111
|
key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4"
|
88
|
-
Rack::Attack.cache.store.read(key).must_equal 1
|
112
|
+
_(Rack::Attack.cache.store.read(key)).must_equal 1
|
89
113
|
end
|
90
114
|
|
91
115
|
it 'should populate throttle data' do
|
92
|
-
data = {
|
93
|
-
|
116
|
+
data = {
|
117
|
+
count: 1,
|
118
|
+
limit: 1,
|
119
|
+
period: @period,
|
120
|
+
epoch_time: Rack::Attack.cache.last_epoch_time.to_i,
|
121
|
+
discriminator: "1.2.3.4"
|
122
|
+
}
|
123
|
+
|
124
|
+
_(last_request.env['rack.attack.throttle_data']['ip/sec']).must_equal data
|
94
125
|
end
|
95
126
|
end
|
96
127
|
end
|
@@ -99,7 +130,7 @@ describe 'Rack::Attack.throttle with block retuning nil' do
|
|
99
130
|
before do
|
100
131
|
@period = 60
|
101
132
|
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
|
102
|
-
Rack::Attack.throttle('ip/sec', :
|
133
|
+
Rack::Attack.throttle('ip/sec', limit: 1, period: @period) { |_| nil }
|
103
134
|
end
|
104
135
|
|
105
136
|
it_allows_ok_requests
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'spec_helper'
|
2
4
|
|
3
5
|
describe 'Rack::Attack.track' do
|
@@ -23,8 +25,9 @@ describe 'Rack::Attack.track' do
|
|
23
25
|
|
24
26
|
it "should tag the env" do
|
25
27
|
get '/'
|
26
|
-
|
27
|
-
last_request.env['rack.attack.
|
28
|
+
|
29
|
+
_(last_request.env['rack.attack.matched']).must_equal 'everything'
|
30
|
+
_(last_request.env['rack.attack.match_type']).must_equal :track
|
28
31
|
end
|
29
32
|
|
30
33
|
describe "with a notification subscriber and two tracks" do
|
@@ -33,7 +36,7 @@ describe 'Rack::Attack.track' do
|
|
33
36
|
# A second track
|
34
37
|
Rack::Attack.track("homepage") { |req| req.path == "/" }
|
35
38
|
|
36
|
-
ActiveSupport::Notifications.subscribe("
|
39
|
+
ActiveSupport::Notifications.subscribe("track.rack_attack") do |*_args|
|
37
40
|
Counter.incr
|
38
41
|
end
|
39
42
|
|
@@ -41,21 +44,23 @@ describe 'Rack::Attack.track' do
|
|
41
44
|
end
|
42
45
|
|
43
46
|
it "should notify twice" do
|
44
|
-
Counter.check.must_equal 2
|
47
|
+
_(Counter.check).must_equal 2
|
45
48
|
end
|
46
49
|
end
|
47
50
|
|
48
51
|
describe "without limit and period options" do
|
49
52
|
it "should assign the track filter to a Check instance" do
|
50
53
|
track = Rack::Attack.track("homepage") { |req| req.path == "/" }
|
51
|
-
|
54
|
+
|
55
|
+
_(track.filter.class).must_equal Rack::Attack::Check
|
52
56
|
end
|
53
57
|
end
|
54
58
|
|
55
59
|
describe "with limit and period options" do
|
56
60
|
it "should assign the track filter to a Throttle instance" do
|
57
|
-
track = Rack::Attack.track("homepage", :
|
58
|
-
|
61
|
+
track = Rack::Attack.track("homepage", limit: 10, period: 10) { |req| req.path == "/" }
|
62
|
+
|
63
|
+
_(track.filter.class).must_equal Rack::Attack::Throttle
|
59
64
|
end
|
60
65
|
end
|
61
66
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "bundler/setup"
|
2
4
|
|
3
5
|
require "minitest/autorun"
|
4
6
|
require "minitest/pride"
|
5
7
|
require "rack/test"
|
6
|
-
require
|
7
|
-
require 'action_dispatch'
|
8
|
+
require "rails"
|
8
9
|
|
9
10
|
require "rack/attack"
|
10
11
|
|
@@ -13,10 +14,9 @@ if RUBY_ENGINE == "ruby"
|
|
13
14
|
end
|
14
15
|
|
15
16
|
def safe_require(name)
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
17
|
+
require name
|
18
|
+
rescue LoadError
|
19
|
+
nil
|
20
20
|
end
|
21
21
|
|
22
22
|
safe_require "connection_pool"
|
@@ -29,6 +29,7 @@ class MiniTest::Spec
|
|
29
29
|
include Rack::Test::Methods
|
30
30
|
|
31
31
|
before do
|
32
|
+
Rails.cache = nil
|
32
33
|
@_original_throttled_response = Rack::Attack.throttled_response
|
33
34
|
@_original_blocklisted_response = Rack::Attack.blocklisted_response
|
34
35
|
end
|
@@ -55,8 +56,9 @@ class MiniTest::Spec
|
|
55
56
|
def self.it_allows_ok_requests
|
56
57
|
it "must allow ok requests" do
|
57
58
|
get '/', {}, 'REMOTE_ADDR' => '127.0.0.1'
|
58
|
-
|
59
|
-
last_response.
|
59
|
+
|
60
|
+
_(last_response.status).must_equal 200
|
61
|
+
_(last_response.body).must_equal 'Hello World'
|
60
62
|
end
|
61
63
|
end
|
62
64
|
end
|