rack-attack 5.4.1 → 6.2.1

Sign up to get free protection for your applications and to get access to all the features.
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