rack-attack 4.3.1 → 5.4.2

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.
Files changed (64) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +230 -113
  3. data/Rakefile +11 -3
  4. data/bin/setup +8 -0
  5. data/lib/rack/attack.rb +121 -48
  6. data/lib/rack/attack/allow2ban.rb +2 -1
  7. data/lib/rack/attack/{whitelist.rb → blocklist.rb} +2 -3
  8. data/lib/rack/attack/cache.rb +24 -5
  9. data/lib/rack/attack/check.rb +6 -8
  10. data/lib/rack/attack/fail2ban.rb +3 -2
  11. data/lib/rack/attack/path_normalizer.rb +6 -11
  12. data/lib/rack/attack/request.rb +1 -1
  13. data/lib/rack/attack/{blacklist.rb → safelist.rb} +2 -4
  14. data/lib/rack/attack/store_proxy.rb +13 -12
  15. data/lib/rack/attack/store_proxy/dalli_proxy.rb +2 -3
  16. data/lib/rack/attack/store_proxy/mem_cache_proxy.rb +50 -0
  17. data/lib/rack/attack/store_proxy/mem_cache_store_proxy.rb +19 -0
  18. data/lib/rack/attack/store_proxy/redis_cache_store_proxy.rb +35 -0
  19. data/lib/rack/attack/store_proxy/redis_proxy.rb +54 -0
  20. data/lib/rack/attack/store_proxy/redis_store_proxy.rb +5 -24
  21. data/lib/rack/attack/throttle.rb +16 -12
  22. data/lib/rack/attack/track.rb +3 -3
  23. data/lib/rack/attack/version.rb +1 -1
  24. data/spec/acceptance/allow2ban_spec.rb +71 -0
  25. data/spec/acceptance/blocking_ip_spec.rb +38 -0
  26. data/spec/acceptance/blocking_spec.rb +41 -0
  27. data/spec/acceptance/blocking_subnet_spec.rb +44 -0
  28. data/spec/acceptance/cache_store_config_for_allow2ban_spec.rb +126 -0
  29. data/spec/acceptance/cache_store_config_for_fail2ban_spec.rb +121 -0
  30. data/spec/acceptance/cache_store_config_for_throttle_spec.rb +48 -0
  31. data/spec/acceptance/cache_store_config_with_rails_spec.rb +31 -0
  32. data/spec/acceptance/customizing_blocked_response_spec.rb +41 -0
  33. data/spec/acceptance/customizing_throttled_response_spec.rb +59 -0
  34. data/spec/acceptance/extending_request_object_spec.rb +34 -0
  35. data/spec/acceptance/fail2ban_spec.rb +76 -0
  36. data/spec/acceptance/safelisting_ip_spec.rb +48 -0
  37. data/spec/acceptance/safelisting_spec.rb +53 -0
  38. data/spec/acceptance/safelisting_subnet_spec.rb +48 -0
  39. data/spec/acceptance/stores/active_support_dalli_store_spec.rb +19 -0
  40. data/spec/acceptance/stores/active_support_mem_cache_store_pooled_spec.rb +22 -0
  41. data/spec/acceptance/stores/active_support_mem_cache_store_spec.rb +18 -0
  42. data/spec/acceptance/stores/active_support_memory_store_spec.rb +16 -0
  43. data/spec/acceptance/stores/active_support_redis_cache_store_pooled_spec.rb +18 -0
  44. data/spec/acceptance/stores/active_support_redis_cache_store_spec.rb +18 -0
  45. data/spec/acceptance/stores/active_support_redis_store_spec.rb +18 -0
  46. data/spec/acceptance/stores/connection_pool_dalli_client_spec.rb +22 -0
  47. data/spec/acceptance/stores/dalli_client_spec.rb +19 -0
  48. data/spec/acceptance/stores/redis_spec.rb +20 -0
  49. data/spec/acceptance/stores/redis_store_spec.rb +18 -0
  50. data/spec/acceptance/throttling_spec.rb +159 -0
  51. data/spec/acceptance/track_spec.rb +27 -0
  52. data/spec/acceptance/track_throttle_spec.rb +53 -0
  53. data/spec/allow2ban_spec.rb +10 -9
  54. data/spec/fail2ban_spec.rb +12 -10
  55. data/spec/integration/offline_spec.rb +21 -23
  56. data/spec/rack_attack_dalli_proxy_spec.rb +0 -2
  57. data/spec/rack_attack_request_spec.rb +2 -2
  58. data/spec/rack_attack_spec.rb +53 -18
  59. data/spec/rack_attack_throttle_spec.rb +45 -13
  60. data/spec/rack_attack_track_spec.rb +11 -8
  61. data/spec/spec_helper.rb +35 -14
  62. data/spec/support/cache_store_helper.rb +82 -0
  63. metadata +161 -61
  64. data/spec/integration/rack_attack_cache_spec.rb +0 -119
@@ -1,4 +1,5 @@
1
1
  require_relative 'spec_helper'
2
+
2
3
  describe 'Rack::Attack.Fail2Ban' do
3
4
  before do
4
5
  # Use a long findtime; failures due to cache key rotation less likely
@@ -6,9 +7,10 @@ describe 'Rack::Attack.Fail2Ban' do
6
7
  @findtime = 60
7
8
  @bantime = 60
8
9
  Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
9
- @f2b_options = {:bantime => @bantime, :findtime => @findtime, :maxretry => 2}
10
- Rack::Attack.blacklist('pentest') do |req|
11
- Rack::Attack::Fail2Ban.filter(req.ip, @f2b_options){req.query_string =~ /OMGHAX/}
10
+ @f2b_options = { :bantime => @bantime, :findtime => @findtime, :maxretry => 2 }
11
+
12
+ Rack::Attack.blocklist('pentest') do |req|
13
+ Rack::Attack::Fail2Ban.filter(req.ip, @f2b_options) { req.query_string =~ /OMGHAX/ }
12
14
  end
13
15
  end
14
16
 
@@ -23,12 +25,13 @@ describe 'Rack::Attack.Fail2Ban' do
23
25
  describe 'making failing request' do
24
26
  describe 'when not at maxretry' do
25
27
  before { get '/?foo=OMGHAX', {}, 'REMOTE_ADDR' => '1.2.3.4' }
28
+
26
29
  it 'fails' do
27
30
  last_response.status.must_equal 403
28
31
  end
29
32
 
30
33
  it 'increases fail count' do
31
- key = "rack::attack:#{Time.now.to_i/@findtime}:fail2ban:count:1.2.3.4"
34
+ key = "rack::attack:#{Time.now.to_i / @findtime}:fail2ban:count:1.2.3.4"
32
35
  @cache.store.read(key).must_equal 1
33
36
  end
34
37
 
@@ -50,7 +53,7 @@ describe 'Rack::Attack.Fail2Ban' do
50
53
  end
51
54
 
52
55
  it 'increases fail count' do
53
- key = "rack::attack:#{Time.now.to_i/@findtime}:fail2ban:count:1.2.3.4"
56
+ key = "rack::attack:#{Time.now.to_i / @findtime}:fail2ban:count:1.2.3.4"
54
57
  @cache.store.read(key).must_equal 2
55
58
  end
56
59
 
@@ -72,8 +75,8 @@ describe 'Rack::Attack.Fail2Ban' do
72
75
  end
73
76
 
74
77
  it 'resets fail count' do
75
- key = "rack::attack:#{Time.now.to_i/@findtime}:fail2ban:count:1.2.3.4"
76
- @cache.store.read(key).must_equal nil
78
+ key = "rack::attack:#{Time.now.to_i / @findtime}:fail2ban:count:1.2.3.4"
79
+ assert_nil @cache.store.read(key)
77
80
  end
78
81
 
79
82
  it 'IP is not banned' do
@@ -107,7 +110,7 @@ describe 'Rack::Attack.Fail2Ban' do
107
110
  end
108
111
 
109
112
  it 'does not increase fail count' do
110
- key = "rack::attack:#{Time.now.to_i/@findtime}:fail2ban:count:1.2.3.4"
113
+ key = "rack::attack:#{Time.now.to_i / @findtime}:fail2ban:count:1.2.3.4"
111
114
  @cache.store.read(key).must_equal 2
112
115
  end
113
116
 
@@ -127,7 +130,7 @@ describe 'Rack::Attack.Fail2Ban' do
127
130
  end
128
131
 
129
132
  it 'does not increase fail count' do
130
- key = "rack::attack:#{Time.now.to_i/@findtime}:fail2ban:count:1.2.3.4"
133
+ key = "rack::attack:#{Time.now.to_i / @findtime}:fail2ban:count:1.2.3.4"
131
134
  @cache.store.read(key).must_equal 2
132
135
  end
133
136
 
@@ -136,6 +139,5 @@ describe 'Rack::Attack.Fail2Ban' do
136
139
  @cache.store.read(key).must_equal 1
137
140
  end
138
141
  end
139
-
140
142
  end
141
143
  end
@@ -1,10 +1,7 @@
1
1
  require 'active_support/cache'
2
- require 'active_support/cache/redis_store'
3
- require 'dalli'
4
2
  require_relative '../spec_helper'
5
3
 
6
4
  OfflineExamples = Minitest::SharedExamples.new do
7
-
8
5
  it 'should write' do
9
6
  @cache.write('cache-test-key', 'foobar', 1)
10
7
  end
@@ -16,32 +13,33 @@ OfflineExamples = Minitest::SharedExamples.new do
16
13
  it 'should count' do
17
14
  @cache.send(:do_count, 'rack::attack::cache-test-key', 1)
18
15
  end
19
-
20
16
  end
21
17
 
22
- describe 'when Redis is offline' do
23
- include OfflineExamples
24
-
25
- before {
26
- @cache = Rack::Attack::Cache.new
27
- # Use presumably unused port for Redis client
28
- @cache.store = ActiveSupport::Cache::RedisStore.new(:host => '127.0.0.1', :port => 3333)
29
- }
18
+ if defined?(::ActiveSupport::Cache::RedisStore)
19
+ describe 'when Redis is offline' do
20
+ include OfflineExamples
30
21
 
22
+ before do
23
+ @cache = Rack::Attack::Cache.new
24
+ # Use presumably unused port for Redis client
25
+ @cache.store = ActiveSupport::Cache::RedisStore.new(:host => '127.0.0.1', :port => 3333)
26
+ end
27
+ end
31
28
  end
32
29
 
33
- describe 'when Memcached is offline' do
34
- include OfflineExamples
35
-
36
- before {
37
- Dalli.logger.level = Logger::FATAL
30
+ if defined?(::Dalli)
31
+ describe 'when Memcached is offline' do
32
+ include OfflineExamples
38
33
 
39
- @cache = Rack::Attack::Cache.new
40
- @cache.store = Dalli::Client.new('127.0.0.1:22122')
41
- }
34
+ before do
35
+ Dalli.logger.level = Logger::FATAL
42
36
 
43
- after {
44
- Dalli.logger.level = Logger::INFO
45
- }
37
+ @cache = Rack::Attack::Cache.new
38
+ @cache.store = Dalli::Client.new('127.0.0.1:22122')
39
+ end
46
40
 
41
+ after do
42
+ Dalli.logger.level = Logger::INFO
43
+ end
44
+ end
47
45
  end
@@ -1,10 +1,8 @@
1
1
  require_relative 'spec_helper'
2
2
 
3
3
  describe Rack::Attack::StoreProxy::DalliProxy do
4
-
5
4
  it 'should stub Dalli::Client#with on older clients' do
6
5
  proxy = Rack::Attack::StoreProxy::DalliProxy.new(Class.new)
7
6
  proxy.with {} # will not raise an error
8
7
  end
9
-
10
8
  end
@@ -9,11 +9,11 @@ describe 'Rack::Attack' do
9
9
  end
10
10
  end
11
11
 
12
- Rack::Attack.whitelist('valid IP') do |req|
12
+ Rack::Attack.safelist('valid IP') do |req|
13
13
  req.remote_ip == "127.0.0.1"
14
14
  end
15
15
  end
16
16
 
17
- allow_ok_requests
17
+ it_allows_ok_requests
18
18
  end
19
19
  end
@@ -1,11 +1,11 @@
1
1
  require_relative 'spec_helper'
2
2
 
3
3
  describe 'Rack::Attack' do
4
- allow_ok_requests
4
+ it_allows_ok_requests
5
5
 
6
6
  describe 'normalizing paths' do
7
7
  before do
8
- Rack::Attack.blacklist("banned_path") {|req| req.path == '/foo' }
8
+ Rack::Attack.blocklist("banned_path") { |req| req.path == '/foo' }
9
9
  end
10
10
 
11
11
  it 'blocks requests with trailing slash' do
@@ -14,50 +14,85 @@ describe 'Rack::Attack' do
14
14
  end
15
15
  end
16
16
 
17
- describe 'blacklist' do
17
+ describe 'blocklist' do
18
18
  before do
19
19
  @bad_ip = '1.2.3.4'
20
- Rack::Attack.blacklist("ip #{@bad_ip}") {|req| req.ip == @bad_ip }
20
+ Rack::Attack.blocklist("ip #{@bad_ip}") { |req| req.ip == @bad_ip }
21
21
  end
22
22
 
23
- it('has a blacklist') {
24
- Rack::Attack.blacklists.key?("ip #{@bad_ip}").must_equal true
23
+ it('has a blocklist') {
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
25
32
  }
26
33
 
27
34
  describe "a bad request" do
28
35
  before { get '/', {}, 'REMOTE_ADDR' => @bad_ip }
29
- it "should return a blacklist response" do
30
- get '/', {}, 'REMOTE_ADDR' => @bad_ip
36
+
37
+ it "should return a blocklist response" do
31
38
  last_response.status.must_equal 403
32
39
  last_response.body.must_equal "Forbidden\n"
33
40
  end
41
+
34
42
  it "should tag the env" do
35
43
  last_request.env['rack.attack.matched'].must_equal "ip #{@bad_ip}"
36
- last_request.env['rack.attack.match_type'].must_equal :blacklist
44
+ last_request.env['rack.attack.match_type'].must_equal :blocklist
37
45
  end
38
46
 
39
- allow_ok_requests
47
+ it_allows_ok_requests
40
48
  end
41
49
 
42
- describe "and whitelist" do
50
+ describe "and safelist" do
43
51
  before do
44
52
  @good_ua = 'GoodUA'
45
- Rack::Attack.whitelist("good ua") {|req| req.user_agent == @good_ua }
53
+ Rack::Attack.safelist("good ua") { |req| req.user_agent == @good_ua }
46
54
  end
47
55
 
48
- it('has a whitelist'){ Rack::Attack.whitelists.key?("good ua") }
49
- describe "with a request match both whitelist & blacklist" do
56
+ it('has a safelist') { Rack::Attack.safelists.key?("good ua") }
57
+
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
+ describe "with a request match both safelist & blocklist" do
50
66
  before { get '/', {}, 'REMOTE_ADDR' => @bad_ip, 'HTTP_USER_AGENT' => @good_ua }
51
- it "should allow whitelists before blacklists" do
52
- get '/', {}, 'REMOTE_ADDR' => @bad_ip, 'HTTP_USER_AGENT' => @good_ua
67
+
68
+ it "should allow safelists before blocklists" do
53
69
  last_response.status.must_equal 200
54
70
  end
71
+
55
72
  it "should tag the env" do
56
73
  last_request.env['rack.attack.matched'].must_equal 'good ua'
57
- last_request.env['rack.attack.match_type'].must_equal :whitelist
74
+ last_request.env['rack.attack.match_type'].must_equal :safelist
58
75
  end
59
76
  end
60
77
  end
61
- end
62
78
 
79
+ describe '#blocklisted_response' do
80
+ 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
89
+ end
90
+ end
91
+
92
+ describe '#throttled_response' do
93
+ it 'should exist' do
94
+ Rack::Attack.throttled_response.must_respond_to :call
95
+ end
96
+ end
97
+ end
63
98
  end
@@ -1,4 +1,5 @@
1
1
  require_relative 'spec_helper'
2
+
2
3
  describe 'Rack::Attack.throttle' do
3
4
  before do
4
5
  @period = 60 # Use a long period; failures due to cache key rotation less likely
@@ -6,34 +7,40 @@ describe 'Rack::Attack.throttle' do
6
7
  Rack::Attack.throttle('ip/sec', :limit => 1, :period => @period) { |req| req.ip }
7
8
  end
8
9
 
9
- it('should have a throttle'){ Rack::Attack.throttles.key?('ip/sec') }
10
- allow_ok_requests
10
+ it('should have a throttle') { Rack::Attack.throttles.key?('ip/sec') }
11
+
12
+ it_allows_ok_requests
11
13
 
12
14
  describe 'a single request' do
13
15
  before { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' }
16
+
14
17
  it 'should set the counter for one request' do
15
- key = "rack::attack:#{Time.now.to_i/@period}:ip/sec:1.2.3.4"
18
+ key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4"
16
19
  Rack::Attack.cache.store.read(key).must_equal 1
17
20
  end
18
21
 
19
22
  it 'should populate throttle data' do
20
- data = { :count => 1, :limit => 1, :period => @period }
23
+ data = { :count => 1, :limit => 1, :period => @period, epoch_time: Rack::Attack.cache.last_epoch_time.to_i }
21
24
  last_request.env['rack.attack.throttle_data']['ip/sec'].must_equal data
22
25
  end
23
26
  end
27
+
24
28
  describe "with 2 requests" do
25
29
  before do
26
30
  2.times { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' }
27
31
  end
32
+
28
33
  it 'should block the last request' do
29
34
  last_response.status.must_equal 429
30
35
  end
36
+
31
37
  it 'should tag the env' do
32
38
  last_request.env['rack.attack.matched'].must_equal 'ip/sec'
33
39
  last_request.env['rack.attack.match_type'].must_equal :throttle
34
- last_request.env['rack.attack.match_data'].must_equal({:count => 2, :limit => 1, :period => @period})
40
+ last_request.env['rack.attack.match_data'].must_equal(:count => 2, :limit => 1, :period => @period, epoch_time: Rack::Attack.cache.last_epoch_time.to_i)
35
41
  last_request.env['rack.attack.match_discriminator'].must_equal('1.2.3.4')
36
42
  end
43
+
37
44
  it 'should set a Retry-After header' do
38
45
  last_response.headers['Retry-After'].must_equal @period.to_s
39
46
  end
@@ -44,20 +51,21 @@ describe 'Rack::Attack.throttle with limit as proc' do
44
51
  before do
45
52
  @period = 60 # Use a long period; failures due to cache key rotation less likely
46
53
  Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
47
- Rack::Attack.throttle('ip/sec', :limit => lambda { |req| 1 }, :period => @period) { |req| req.ip }
54
+ Rack::Attack.throttle('ip/sec', :limit => lambda { |_req| 1 }, :period => @period) { |req| req.ip }
48
55
  end
49
56
 
50
- allow_ok_requests
57
+ it_allows_ok_requests
51
58
 
52
59
  describe 'a single request' do
53
60
  before { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' }
61
+
54
62
  it 'should set the counter for one request' do
55
- key = "rack::attack:#{Time.now.to_i/@period}:ip/sec:1.2.3.4"
63
+ key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4"
56
64
  Rack::Attack.cache.store.read(key).must_equal 1
57
65
  end
58
66
 
59
67
  it 'should populate throttle data' do
60
- data = { :count => 1, :limit => 1, :period => @period }
68
+ data = { :count => 1, :limit => 1, :period => @period, epoch_time: Rack::Attack.cache.last_epoch_time.to_i }
61
69
  last_request.env['rack.attack.throttle_data']['ip/sec'].must_equal data
62
70
  end
63
71
  end
@@ -67,21 +75,45 @@ describe 'Rack::Attack.throttle with period as proc' do
67
75
  before do
68
76
  @period = 60 # Use a long period; failures due to cache key rotation less likely
69
77
  Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
70
- Rack::Attack.throttle('ip/sec', :limit => lambda { |req| 1 }, :period => lambda { |req| @period }) { |req| req.ip }
78
+ Rack::Attack.throttle('ip/sec', :limit => lambda { |_req| 1 }, :period => lambda { |_req| @period }) { |req| req.ip }
71
79
  end
72
80
 
73
- allow_ok_requests
81
+ it_allows_ok_requests
74
82
 
75
83
  describe 'a single request' do
76
84
  before { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' }
85
+
77
86
  it 'should set the counter for one request' do
78
- key = "rack::attack:#{Time.now.to_i/@period}:ip/sec:1.2.3.4"
87
+ key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4"
79
88
  Rack::Attack.cache.store.read(key).must_equal 1
80
89
  end
81
90
 
82
91
  it 'should populate throttle data' do
83
- data = { :count => 1, :limit => 1, :period => @period }
92
+ data = { :count => 1, :limit => 1, :period => @period, epoch_time: Rack::Attack.cache.last_epoch_time.to_i }
84
93
  last_request.env['rack.attack.throttle_data']['ip/sec'].must_equal data
85
94
  end
86
95
  end
87
96
  end
97
+
98
+ describe 'Rack::Attack.throttle with block retuning nil' do
99
+ before do
100
+ @period = 60
101
+ Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
102
+ Rack::Attack.throttle('ip/sec', :limit => 1, :period => @period) { |_| nil }
103
+ end
104
+
105
+ it_allows_ok_requests
106
+
107
+ describe 'a single request' do
108
+ before { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' }
109
+
110
+ it 'should not set the counter' do
111
+ key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4"
112
+ assert_nil Rack::Attack.cache.store.read(key)
113
+ end
114
+
115
+ it 'should not populate throttle data' do
116
+ assert_nil last_request.env['rack.attack.throttle_data']
117
+ end
118
+ end
119
+ end
@@ -16,9 +16,11 @@ describe 'Rack::Attack.track' do
16
16
  end
17
17
 
18
18
  before do
19
- Rack::Attack.track("everything"){ |req| true }
19
+ Rack::Attack.track("everything") { |_req| true }
20
20
  end
21
- allow_ok_requests
21
+
22
+ it_allows_ok_requests
23
+
22
24
  it "should tag the env" do
23
25
  get '/'
24
26
  last_request.env['rack.attack.matched'].must_equal 'everything'
@@ -29,11 +31,12 @@ describe 'Rack::Attack.track' do
29
31
  before do
30
32
  Counter.reset
31
33
  # A second track
32
- Rack::Attack.track("homepage"){ |req| req.path == "/"}
34
+ Rack::Attack.track("homepage") { |req| req.path == "/" }
33
35
 
34
- ActiveSupport::Notifications.subscribe("rack.attack") do |*args|
36
+ ActiveSupport::Notifications.subscribe("rack.attack") do |*_args|
35
37
  Counter.incr
36
38
  end
39
+
37
40
  get "/"
38
41
  end
39
42
 
@@ -44,15 +47,15 @@ describe 'Rack::Attack.track' do
44
47
 
45
48
  describe "without limit and period options" do
46
49
  it "should assign the track filter to a Check instance" do
47
- tracker = Rack::Attack.track("homepage") { |req| req.path == "/"}
48
- tracker.filter.class.must_equal Rack::Attack::Check
50
+ track = Rack::Attack.track("homepage") { |req| req.path == "/" }
51
+ track.filter.class.must_equal Rack::Attack::Check
49
52
  end
50
53
  end
51
54
 
52
55
  describe "with limit and period options" do
53
56
  it "should assign the track filter to a Throttle instance" do
54
- tracker = Rack::Attack.track("homepage", :limit => 10, :period => 10) { |req| req.path == "/"}
55
- tracker.filter.class.must_equal Rack::Attack::Throttle
57
+ track = Rack::Attack.track("homepage", :limit => 10, :period => 10) { |req| req.path == "/" }
58
+ track.filter.class.must_equal Rack::Attack::Throttle
56
59
  end
57
60
  end
58
61
  end