rack-attack 5.4.1 → 6.2.1

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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +78 -27
  3. data/Rakefile +3 -1
  4. data/lib/rack/attack.rb +138 -149
  5. data/lib/rack/attack/allow2ban.rb +2 -0
  6. data/lib/rack/attack/blocklist.rb +3 -1
  7. data/lib/rack/attack/cache.rb +9 -4
  8. data/lib/rack/attack/check.rb +5 -2
  9. data/lib/rack/attack/fail2ban.rb +2 -0
  10. data/lib/rack/attack/path_normalizer.rb +22 -18
  11. data/lib/rack/attack/railtie.rb +13 -0
  12. data/lib/rack/attack/request.rb +2 -0
  13. data/lib/rack/attack/safelist.rb +3 -1
  14. data/lib/rack/attack/store_proxy.rb +12 -14
  15. data/lib/rack/attack/store_proxy/active_support_redis_store_proxy.rb +39 -0
  16. data/lib/rack/attack/store_proxy/dalli_proxy.rb +27 -13
  17. data/lib/rack/attack/store_proxy/mem_cache_store_proxy.rb +3 -1
  18. data/lib/rack/attack/store_proxy/redis_cache_store_proxy.rb +23 -9
  19. data/lib/rack/attack/store_proxy/redis_proxy.rb +16 -10
  20. data/lib/rack/attack/store_proxy/redis_store_proxy.rb +5 -5
  21. data/lib/rack/attack/throttle.rb +12 -8
  22. data/lib/rack/attack/track.rb +9 -6
  23. data/lib/rack/attack/version.rb +3 -1
  24. data/spec/acceptance/allow2ban_spec.rb +2 -0
  25. data/spec/acceptance/blocking_ip_spec.rb +4 -2
  26. data/spec/acceptance/blocking_spec.rb +45 -3
  27. data/spec/acceptance/blocking_subnet_spec.rb +4 -2
  28. data/spec/acceptance/cache_store_config_for_allow2ban_spec.rb +50 -39
  29. data/spec/acceptance/cache_store_config_for_fail2ban_spec.rb +38 -29
  30. data/spec/acceptance/cache_store_config_for_throttle_spec.rb +2 -0
  31. data/spec/acceptance/cache_store_config_with_rails_spec.rb +2 -0
  32. data/spec/acceptance/customizing_blocked_response_spec.rb +2 -0
  33. data/spec/acceptance/customizing_throttled_response_spec.rb +2 -0
  34. data/spec/acceptance/extending_request_object_spec.rb +2 -0
  35. data/spec/acceptance/fail2ban_spec.rb +2 -0
  36. data/spec/acceptance/rails_middleware_spec.rb +35 -0
  37. data/spec/acceptance/safelisting_ip_spec.rb +4 -2
  38. data/spec/acceptance/safelisting_spec.rb +57 -3
  39. data/spec/acceptance/safelisting_subnet_spec.rb +4 -2
  40. data/spec/acceptance/stores/active_support_dalli_store_spec.rb +2 -0
  41. data/spec/acceptance/stores/active_support_mem_cache_store_pooled_spec.rb +1 -3
  42. data/spec/acceptance/stores/active_support_mem_cache_store_spec.rb +2 -0
  43. data/spec/acceptance/stores/active_support_memory_store_spec.rb +2 -0
  44. data/spec/acceptance/stores/active_support_redis_cache_store_pooled_spec.rb +9 -1
  45. data/spec/acceptance/stores/active_support_redis_cache_store_spec.rb +8 -1
  46. data/spec/acceptance/stores/active_support_redis_store_spec.rb +3 -1
  47. data/spec/acceptance/stores/connection_pool_dalli_client_spec.rb +5 -3
  48. data/spec/acceptance/stores/dalli_client_spec.rb +2 -0
  49. data/spec/acceptance/stores/redis_store_spec.rb +2 -0
  50. data/spec/acceptance/throttling_spec.rb +7 -5
  51. data/spec/acceptance/track_spec.rb +5 -3
  52. data/spec/acceptance/track_throttle_spec.rb +5 -3
  53. data/spec/allow2ban_spec.rb +20 -15
  54. data/spec/fail2ban_spec.rb +20 -17
  55. data/spec/integration/offline_spec.rb +3 -1
  56. data/spec/rack_attack_dalli_proxy_spec.rb +2 -0
  57. data/spec/rack_attack_instrumentation_spec.rb +42 -0
  58. data/spec/rack_attack_path_normalizer_spec.rb +4 -2
  59. data/spec/rack_attack_request_spec.rb +2 -0
  60. data/spec/rack_attack_spec.rb +38 -34
  61. data/spec/rack_attack_throttle_spec.rb +50 -19
  62. data/spec/rack_attack_track_spec.rb +12 -7
  63. data/spec/spec_helper.rb +12 -8
  64. data/spec/support/cache_store_helper.rb +2 -0
  65. metadata +44 -28
  66. 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_relative 'spec_helper'
2
4
 
3
5
  describe 'Rack::Attack.Fail2Ban' do
@@ -7,7 +9,7 @@ describe 'Rack::Attack.Fail2Ban' do
7
9
  @findtime = 60
8
10
  @bantime = 60
9
11
  Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
10
- @f2b_options = { :bantime => @bantime, :findtime => @findtime, :maxretry => 2 }
12
+ @f2b_options = { bantime: @bantime, findtime: @findtime, maxretry: 2 }
11
13
 
12
14
  Rack::Attack.blocklist('pentest') do |req|
13
15
  Rack::Attack::Fail2Ban.filter(req.ip, @f2b_options) { req.query_string =~ /OMGHAX/ }
@@ -18,7 +20,7 @@ describe 'Rack::Attack.Fail2Ban' do
18
20
  describe 'making ok request' do
19
21
  it 'succeeds' do
20
22
  get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
21
- last_response.status.must_equal 200
23
+ _(last_response.status).must_equal 200
22
24
  end
23
25
  end
24
26
 
@@ -27,17 +29,17 @@ describe 'Rack::Attack.Fail2Ban' do
27
29
  before { get '/?foo=OMGHAX', {}, 'REMOTE_ADDR' => '1.2.3.4' }
28
30
 
29
31
  it 'fails' do
30
- last_response.status.must_equal 403
32
+ _(last_response.status).must_equal 403
31
33
  end
32
34
 
33
35
  it 'increases fail count' do
34
36
  key = "rack::attack:#{Time.now.to_i / @findtime}:fail2ban:count:1.2.3.4"
35
- @cache.store.read(key).must_equal 1
37
+ _(@cache.store.read(key)).must_equal 1
36
38
  end
37
39
 
38
40
  it 'is not banned' do
39
41
  key = "rack::attack:fail2ban:1.2.3.4"
40
- @cache.store.read(key).must_be_nil
42
+ _(@cache.store.read(key)).must_be_nil
41
43
  end
42
44
  end
43
45
 
@@ -49,17 +51,17 @@ describe 'Rack::Attack.Fail2Ban' do
49
51
  end
50
52
 
51
53
  it 'fails' do
52
- last_response.status.must_equal 403
54
+ _(last_response.status).must_equal 403
53
55
  end
54
56
 
55
57
  it 'increases fail count' do
56
58
  key = "rack::attack:#{Time.now.to_i / @findtime}:fail2ban:count:1.2.3.4"
57
- @cache.store.read(key).must_equal 2
59
+ _(@cache.store.read(key)).must_equal 2
58
60
  end
59
61
 
60
62
  it 'is banned' do
61
63
  key = "rack::attack:fail2ban:ban:1.2.3.4"
62
- @cache.store.read(key).must_equal 1
64
+ _(@cache.store.read(key)).must_equal 1
63
65
  end
64
66
  end
65
67
 
@@ -71,7 +73,7 @@ describe 'Rack::Attack.Fail2Ban' do
71
73
  end
72
74
 
73
75
  it 'succeeds' do
74
- last_response.status.must_equal 200
76
+ _(last_response.status).must_equal 200
75
77
  end
76
78
 
77
79
  it 'resets fail count' do
@@ -80,7 +82,7 @@ describe 'Rack::Attack.Fail2Ban' do
80
82
  end
81
83
 
82
84
  it 'IP is not banned' do
83
- Rack::Attack::Fail2Ban.banned?('1.2.3.4').must_equal false
85
+ _(Rack::Attack::Fail2Ban.banned?('1.2.3.4')).must_equal false
84
86
  end
85
87
  end
86
88
  end
@@ -96,7 +98,8 @@ describe 'Rack::Attack.Fail2Ban' do
96
98
  describe 'making request for other discriminator' do
97
99
  it 'succeeds' do
98
100
  get '/', {}, 'REMOTE_ADDR' => '2.2.3.4'
99
- last_response.status.must_equal 200
101
+
102
+ _(last_response.status).must_equal 200
100
103
  end
101
104
  end
102
105
 
@@ -106,17 +109,17 @@ describe 'Rack::Attack.Fail2Ban' do
106
109
  end
107
110
 
108
111
  it 'fails' do
109
- last_response.status.must_equal 403
112
+ _(last_response.status).must_equal 403
110
113
  end
111
114
 
112
115
  it 'does not increase fail count' do
113
116
  key = "rack::attack:#{Time.now.to_i / @findtime}:fail2ban:count:1.2.3.4"
114
- @cache.store.read(key).must_equal 2
117
+ _(@cache.store.read(key)).must_equal 2
115
118
  end
116
119
 
117
120
  it 'is still banned' do
118
121
  key = "rack::attack:fail2ban:ban:1.2.3.4"
119
- @cache.store.read(key).must_equal 1
122
+ _(@cache.store.read(key)).must_equal 1
120
123
  end
121
124
  end
122
125
 
@@ -126,17 +129,17 @@ describe 'Rack::Attack.Fail2Ban' do
126
129
  end
127
130
 
128
131
  it 'fails' do
129
- last_response.status.must_equal 403
132
+ _(last_response.status).must_equal 403
130
133
  end
131
134
 
132
135
  it 'does not increase fail count' do
133
136
  key = "rack::attack:#{Time.now.to_i / @findtime}:fail2ban:count:1.2.3.4"
134
- @cache.store.read(key).must_equal 2
137
+ _(@cache.store.read(key)).must_equal 2
135
138
  end
136
139
 
137
140
  it 'is still banned' do
138
141
  key = "rack::attack:fail2ban:ban:1.2.3.4"
139
- @cache.store.read(key).must_equal 1
142
+ _(@cache.store.read(key)).must_equal 1
140
143
  end
141
144
  end
142
145
  end
@@ -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(:host => '127.0.0.1', :port => 3333)
27
+ @cache.store = ActiveSupport::Cache::RedisStore.new(host: '127.0.0.1', port: 3333)
26
28
  end
27
29
  end
28
30
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'spec_helper'
2
4
 
3
5
  describe Rack::Attack::StoreProxy::DalliProxy do
@@ -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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'spec_helper'
2
4
 
3
5
  describe 'Rack::Attack' do
@@ -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('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
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', :limit => 1, :period => @period) { |req| req.ip }
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 = { :count => 1, :limit => 1, :period => @period, epoch_time: Rack::Attack.cache.last_epoch_time.to_i }
24
- last_request.env['rack.attack.throttle_data']['ip/sec'].must_equal data
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
- 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)
41
- last_request.env['rack.attack.match_discriminator'].must_equal('1.2.3.4')
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', :limit => lambda { |_req| 1 }, :period => @period) { |req| req.ip }
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 = { :count => 1, :limit => 1, :period => @period, epoch_time: Rack::Attack.cache.last_epoch_time.to_i }
69
- last_request.env['rack.attack.throttle_data']['ip/sec'].must_equal data
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', :limit => lambda { |_req| 1 }, :period => lambda { |_req| @period }) { |req| req.ip }
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 = { :count => 1, :limit => 1, :period => @period, epoch_time: Rack::Attack.cache.last_epoch_time.to_i }
93
- last_request.env['rack.attack.throttle_data']['ip/sec'].must_equal data
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', :limit => 1, :period => @period) { |_| nil }
133
+ Rack::Attack.throttle('ip/sec', limit: 1, period: @period) { |_| nil }
103
134
  end
104
135
 
105
136
  it_allows_ok_requests