rack-attack 5.4.2 → 6.0.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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +65 -23
  3. data/Rakefile +3 -1
  4. data/lib/rack/attack.rb +46 -70
  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 +5 -3
  8. data/lib/rack/attack/check.rb +3 -1
  9. data/lib/rack/attack/fail2ban.rb +2 -0
  10. data/lib/rack/attack/path_normalizer.rb +2 -0
  11. data/lib/rack/attack/request.rb +2 -0
  12. data/lib/rack/attack/safelist.rb +3 -1
  13. data/lib/rack/attack/store_proxy.rb +12 -14
  14. data/lib/rack/attack/store_proxy/active_support_redis_store_proxy.rb +37 -0
  15. data/lib/rack/attack/store_proxy/dalli_proxy.rb +27 -13
  16. data/lib/rack/attack/store_proxy/redis_cache_store_proxy.rb +2 -4
  17. data/lib/rack/attack/store_proxy/redis_proxy.rb +16 -10
  18. data/lib/rack/attack/store_proxy/redis_store_proxy.rb +5 -5
  19. data/lib/rack/attack/throttle.rb +8 -6
  20. data/lib/rack/attack/track.rb +5 -3
  21. data/lib/rack/attack/version.rb +3 -1
  22. data/spec/acceptance/allow2ban_spec.rb +2 -0
  23. data/spec/acceptance/blocking_ip_spec.rb +4 -2
  24. data/spec/acceptance/blocking_spec.rb +45 -3
  25. data/spec/acceptance/blocking_subnet_spec.rb +4 -2
  26. data/spec/acceptance/cache_store_config_for_allow2ban_spec.rb +8 -12
  27. data/spec/acceptance/cache_store_config_for_fail2ban_spec.rb +8 -12
  28. data/spec/acceptance/cache_store_config_for_throttle_spec.rb +2 -0
  29. data/spec/acceptance/cache_store_config_with_rails_spec.rb +2 -0
  30. data/spec/acceptance/customizing_blocked_response_spec.rb +2 -0
  31. data/spec/acceptance/customizing_throttled_response_spec.rb +2 -0
  32. data/spec/acceptance/extending_request_object_spec.rb +2 -0
  33. data/spec/acceptance/fail2ban_spec.rb +2 -0
  34. data/spec/acceptance/safelisting_ip_spec.rb +4 -2
  35. data/spec/acceptance/safelisting_spec.rb +57 -3
  36. data/spec/acceptance/safelisting_subnet_spec.rb +4 -2
  37. data/spec/acceptance/stores/active_support_dalli_store_spec.rb +2 -0
  38. data/spec/acceptance/stores/active_support_mem_cache_store_spec.rb +2 -0
  39. data/spec/acceptance/stores/active_support_memory_store_spec.rb +2 -0
  40. data/spec/acceptance/stores/active_support_redis_cache_store_pooled_spec.rb +2 -0
  41. data/spec/acceptance/stores/active_support_redis_cache_store_spec.rb +2 -0
  42. data/spec/acceptance/stores/active_support_redis_store_spec.rb +3 -1
  43. data/spec/acceptance/stores/connection_pool_dalli_client_spec.rb +2 -0
  44. data/spec/acceptance/stores/dalli_client_spec.rb +2 -0
  45. data/spec/acceptance/stores/redis_store_spec.rb +2 -0
  46. data/spec/acceptance/throttling_spec.rb +7 -5
  47. data/spec/acceptance/track_spec.rb +5 -3
  48. data/spec/acceptance/track_throttle_spec.rb +5 -3
  49. data/spec/allow2ban_spec.rb +3 -1
  50. data/spec/fail2ban_spec.rb +3 -1
  51. data/spec/integration/offline_spec.rb +3 -1
  52. data/spec/rack_attack_dalli_proxy_spec.rb +2 -0
  53. data/spec/rack_attack_instrumentation_spec.rb +42 -0
  54. data/spec/rack_attack_path_normalizer_spec.rb +2 -0
  55. data/spec/rack_attack_request_spec.rb +2 -0
  56. data/spec/rack_attack_spec.rb +2 -21
  57. data/spec/rack_attack_throttle_spec.rb +10 -8
  58. data/spec/rack_attack_track_spec.rb +4 -2
  59. data/spec/spec_helper.rb +5 -4
  60. data/spec/support/cache_store_helper.rb +2 -0
  61. metadata +21 -14
  62. data/lib/rack/attack/store_proxy/mem_cache_proxy.rb +0 -50
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e666812691cc414692f7125979f0b152a9111ccee075e65b811fa4a6d8770daa
4
- data.tar.gz: 3e8caba79f7ad09d4999cce6358de9cc29b815dee3c9f9c5adbf12763c764656
3
+ metadata.gz: f85825803ce676e10466175d4bb99cc151d649130d6f4008bdffdc1381b4650a
4
+ data.tar.gz: 2bcd9d6a9d75491df5a9ddf2f7a5128eae152245fce8f27a069f36037ebc8ddb
5
5
  SHA512:
6
- metadata.gz: f630c0cd1a34bd588e616653a2e6795e2ec6baafc0e0df8b489e6aa451cf47fb64065447fb3ceb2b029a51d87a0393d6d44cea02e58423626ea46165531f7da3
7
- data.tar.gz: 22efc414db06b0a1bbbf8e6d34a3e0d0ead64f1832f48dc30af7ec0a374ef215d53cacf0a8e95c842bff0af84df0939f27820e4668c739eb8db3c51ebba4088e
6
+ metadata.gz: 5c9b03bbb0e55105ebe4d2ea9a0f13a025ea7ab4903f86e07956ecbd7f7ddfcacfecbbc8239bc9ac427fcc4bd5445fa85e20732bd4d90b51f6dafeb7194bc063
7
+ data.tar.gz: a31dad7fb5c9220d4a44b303103ffb12cb23843bc150b14cec38a9d0151bc73791a66a80e8a543fa09f58d36a7b0627f0b5fda4fb93953d525747840d7e1d97f
data/README.md CHANGED
@@ -10,9 +10,42 @@ See the [Backing & Hacking blog post](https://www.kickstarter.com/backing-and-ha
10
10
  [![Build Status](https://travis-ci.org/kickstarter/rack-attack.svg?branch=master)](https://travis-ci.org/kickstarter/rack-attack)
11
11
  [![Code Climate](https://codeclimate.com/github/kickstarter/rack-attack.svg)](https://codeclimate.com/github/kickstarter/rack-attack)
12
12
 
13
+ ## Table of contents
14
+
15
+ - [Getting started](#getting-started)
16
+ - [Installing](#installing)
17
+ - [Plugging into the application](#plugging-into-the-application)
18
+ - [Usage](#usage)
19
+ - [Safelisting](#safelisting)
20
+ - [`safelist_ip(ip_address_string)`](#safelist_ipip_address_string)
21
+ - [`safelist_ip(ip_subnet_string)`](#safelist_ipip_subnet_string)
22
+ - [`safelist(name, &block)`](#safelistname-block)
23
+ - [Blocking](#blocking)
24
+ - [`blocklist_ip(ip_address_string)`](#blocklist_ipip_address_string)
25
+ - [`blocklist_ip(ip_subnet_string)`](#blocklist_ipip_subnet_string)
26
+ - [`blocklist(name, &block)`](#blocklistname-block)
27
+ - [Fail2Ban](#fail2ban)
28
+ - [Allow2Ban](#allow2ban)
29
+ - [Throttling](#throttling)
30
+ - [`throttle(name, options, &block)`](#throttlename-options-block)
31
+ - [Tracks](#tracks)
32
+ - [Cache store configuration](#cache-store-configuration)
33
+ - [Customizing responses](#customizing-responses)
34
+ - [RateLimit headers for well-behaved clients](#ratelimit-headers-for-well-behaved-clients)
35
+ - [Logging & Instrumentation](#logging--instrumentation)
36
+ - [How it works](#how-it-works)
37
+ - [About Tracks](#about-tracks)
38
+ - [Testing](#testing)
39
+ - [Performance](#performance)
40
+ - [Motivation](#motivation)
41
+ - [Contributing](#contributing)
42
+ - [Code of Conduct](#code-of-conduct)
43
+ - [Development setup](#development-setup)
44
+ - [License](#license)
45
+
13
46
  ## Getting started
14
47
 
15
- ### 1. Installing
48
+ ### Installing
16
49
 
17
50
  Add this line to your application's Gemfile:
18
51
 
@@ -30,7 +63,7 @@ Or install it yourself as:
30
63
 
31
64
  $ gem install rack-attack
32
65
 
33
- ### 2. Plugging into the application
66
+ ### Plugging into the application
34
67
 
35
68
  Then tell your ruby web application to use rack-attack as a middleware.
36
69
 
@@ -55,8 +88,8 @@ __IMPORTANT__: By default, rack-attack won't perform any blocking or throttling,
55
88
 
56
89
  ## Usage
57
90
 
58
- *Tip:* The example in the wiki is a great way to get started:
59
- [Example Configuration](https://github.com/kickstarter/rack-attack/wiki/Example-Configuration)
91
+ *Tip:* If you just want to get going asap, then you can take our [example configuration](docs/example_configuration.md)
92
+ and tailor it to your needs, or check out the [advanced configuration](docs/advanced_configuration.md) examples.
60
93
 
61
94
  Define rules by calling `Rack::Attack` public methods, in any file that runs when your application is being initialized. For rails applications this means creating a new file named `config/initializers/rack_attack.rb` and writing your rules there.
62
95
 
@@ -86,7 +119,7 @@ Rack::Attack.safelist_ip("5.6.7.0/24")
86
119
 
87
120
  #### `safelist(name, &block)`
88
121
 
89
- Name your custom safelist and make your ruby-block argument return a truthy value if you want the request to be blocked, and falsy otherwise.
122
+ Name your custom safelist and make your ruby-block argument return a truthy value if you want the request to be allowed, and falsy otherwise.
90
123
 
91
124
  The request object is a [Rack::Request](http://www.rubydoc.info/gems/rack/Rack/Request).
92
125
 
@@ -252,7 +285,8 @@ Rack::Attack.track("special_agent", limit: 6, period: 60) do |req|
252
285
  end
253
286
 
254
287
  # Track it using ActiveSupport::Notification
255
- ActiveSupport::Notifications.subscribe("rack.attack") do |name, start, finish, request_id, req|
288
+ ActiveSupport::Notifications.subscribe("rack.attack") do |name, start, finish, request_id, payload|
289
+ req = payload[:request]
256
290
  if req.env['rack.attack.matched'] == "special_agent" && req.env['rack.attack.match_type'] == :track
257
291
  Rails.logger.info "special_agent: #{req.path}"
258
292
  STATSD.increment("special_agent")
@@ -294,12 +328,12 @@ Rack::Attack.throttled_response = lambda do |env|
294
328
  end
295
329
  ```
296
330
 
297
- ### X-RateLimit headers for well-behaved clients
331
+ ### RateLimit headers for well-behaved clients
298
332
 
299
333
  While Rack::Attack's primary focus is minimizing harm from abusive clients, it
300
334
  can also be used to return rate limit data that's helpful for well-behaved clients.
301
335
 
302
- Here's an example response that includes conventional `X-RateLimit-*` headers:
336
+ Here's an example response that includes conventional `RateLimit-*` headers:
303
337
 
304
338
  ```ruby
305
339
  Rack::Attack.throttled_response = lambda do |env|
@@ -307,9 +341,9 @@ Rack::Attack.throttled_response = lambda do |env|
307
341
  now = match_data[:epoch_time]
308
342
 
309
343
  headers = {
310
- 'X-RateLimit-Limit' => match_data[:limit].to_s,
311
- 'X-RateLimit-Remaining' => '0',
312
- 'X-RateLimit-Reset' => (now + (match_data[:period] - now % match_data[:period])).to_s
344
+ 'RateLimit-Limit' => match_data[:limit].to_s,
345
+ 'RateLimit-Remaining' => '0',
346
+ 'RateLimit-Reset' => (now + (match_data[:period] - now % match_data[:period])).to_s
313
347
  }
314
348
 
315
349
  [ 429, headers, ["Throttled\n"]]
@@ -327,11 +361,26 @@ request.env['rack.attack.throttle_data'][name] # => { :count => n, :period => p,
327
361
 
328
362
  Rack::Attack uses the [ActiveSupport::Notifications](http://api.rubyonrails.org/classes/ActiveSupport/Notifications.html) API if available.
329
363
 
330
- You can subscribe to 'rack.attack' events and log it, graph it, etc:
364
+ You can subscribe to `rack_attack` events and log it, graph it, etc.
365
+
366
+ To get notified about specific type of events, subscribe to the event name followed by the `rack_attack` namesapce.
367
+ E.g. for throttles use:
331
368
 
332
369
  ```ruby
333
- ActiveSupport::Notifications.subscribe('rack.attack') do |name, start, finish, request_id, req|
334
- puts req.inspect
370
+ ActiveSupport::Notifications.subscribe("throttle.rack_attack") do |name, start, finish, request_id, payload|
371
+ # request object available in payload[:request]
372
+
373
+ # Your code here
374
+ end
375
+ ```
376
+
377
+ If you want to subscribe to every `rack_attack` event, use:
378
+
379
+ ```ruby
380
+ ActiveSupport::Notifications.subscribe(/rack_attack/) do |name, start, finish, request_id, payload|
381
+ # request object available in payload[:request]
382
+
383
+ # Your code here
335
384
  end
336
385
  ```
337
386
 
@@ -344,7 +393,7 @@ The Rack::Attack middleware compares each request against *safelists*, *blocklis
344
393
  * Otherwise, if the request matches any **throttle**, a counter is incremented in the Rack::Attack.cache. If any throttle's limit is exceeded, the request is blocked.
345
394
  * Otherwise, all **tracks** are checked, and the request is allowed.
346
395
 
347
- The algorithm is actually more concise in code: See [Rack::Attack.call](https://github.com/kickstarter/rack-attack/blob/master/lib/rack/attack.rb):
396
+ The algorithm is actually more concise in code: See [Rack::Attack.call](lib/rack/attack.rb):
348
397
 
349
398
  ```ruby
350
399
  def call(env)
@@ -365,7 +414,7 @@ end
365
414
 
366
415
  Note: `Rack::Attack::Request` is just a subclass of `Rack::Request` so that you
367
416
  can cleanly monkey patch helper methods onto the
368
- [request object](https://github.com/kickstarter/rack-attack/blob/master/lib/rack/attack/request.rb).
417
+ [request object](lib/rack/attack/request.rb).
369
418
 
370
419
  ### About Tracks
371
420
 
@@ -412,13 +461,6 @@ This project is intended to be a safe, welcoming space for collaboration, and co
412
461
 
413
462
  Check out the [Development guide](docs/development.md).
414
463
 
415
- ## Mailing list
416
-
417
- New releases of Rack::Attack are announced on
418
- <rack.attack.announce@librelist.com>. To subscribe, just send an email to
419
- <rack.attack.announce@librelist.com>. See the
420
- [archives](http://librelist.com/browser/rack.attack.announce/).
421
-
422
464
  ## License
423
465
 
424
466
  Copyright Kickstarter, PBC.
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "rubygems"
2
4
  require "bundler/setup"
3
5
  require 'bundler/gem_tasks'
@@ -24,4 +26,4 @@ Rake::TestTask.new(:test) do |t|
24
26
  t.pattern = "spec/**/*_spec.rb"
25
27
  end
26
28
 
27
- task :default => [:rubocop, :test]
29
+ task default: [:rubocop, :test]
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rack'
2
4
  require 'forwardable'
3
5
  require 'rack/attack/path_normalizer'
@@ -16,93 +18,79 @@ class Rack::Attack
16
18
  autoload :Track, 'rack/attack/track'
17
19
  autoload :StoreProxy, 'rack/attack/store_proxy'
18
20
  autoload :DalliProxy, 'rack/attack/store_proxy/dalli_proxy'
19
- autoload :MemCacheProxy, 'rack/attack/store_proxy/mem_cache_proxy'
20
21
  autoload :MemCacheStoreProxy, 'rack/attack/store_proxy/mem_cache_store_proxy'
21
22
  autoload :RedisProxy, 'rack/attack/store_proxy/redis_proxy'
22
23
  autoload :RedisStoreProxy, 'rack/attack/store_proxy/redis_store_proxy'
23
24
  autoload :RedisCacheStoreProxy, 'rack/attack/store_proxy/redis_cache_store_proxy'
25
+ autoload :ActiveSupportRedisStoreProxy, 'rack/attack/store_proxy/active_support_redis_store_proxy'
24
26
  autoload :Fail2Ban, 'rack/attack/fail2ban'
25
27
  autoload :Allow2Ban, 'rack/attack/allow2ban'
26
28
 
27
29
  class << self
28
- attr_accessor :notifier, :blocklisted_response, :throttled_response
30
+ attr_accessor :notifier, :blocklisted_response, :throttled_response, :anonymous_blocklists, :anonymous_safelists
29
31
 
30
- def safelist(name, &block)
31
- self.safelists[name] = Safelist.new(name, block)
32
- end
32
+ def safelist(name = nil, &block)
33
+ safelist = Safelist.new(name, &block)
33
34
 
34
- def whitelist(name, &block)
35
- warn "[DEPRECATION] 'Rack::Attack.whitelist' is deprecated. Please use 'safelist' instead."
36
- safelist(name, &block)
35
+ if name
36
+ safelists[name] = safelist
37
+ else
38
+ anonymous_safelists << safelist
39
+ end
37
40
  end
38
41
 
39
- def blocklist(name, &block)
40
- self.blocklists[name] = Blocklist.new(name, block)
42
+ def blocklist(name = nil, &block)
43
+ blocklist = Blocklist.new(name, &block)
44
+
45
+ if name
46
+ blocklists[name] = blocklist
47
+ else
48
+ anonymous_blocklists << blocklist
49
+ end
41
50
  end
42
51
 
43
52
  def blocklist_ip(ip_address)
44
- @ip_blocklists ||= []
45
- ip_blocklist_proc = lambda { |request| IPAddr.new(ip_address).include?(IPAddr.new(request.ip)) }
46
- @ip_blocklists << Blocklist.new(nil, ip_blocklist_proc)
53
+ anonymous_blocklists << Blocklist.new { |request| IPAddr.new(ip_address).include?(IPAddr.new(request.ip)) }
47
54
  end
48
55
 
49
56
  def safelist_ip(ip_address)
50
- @ip_safelists ||= []
51
- ip_safelist_proc = lambda { |request| IPAddr.new(ip_address).include?(IPAddr.new(request.ip)) }
52
- @ip_safelists << Safelist.new(nil, ip_safelist_proc)
53
- end
54
-
55
- def blacklist(name, &block)
56
- warn "[DEPRECATION] 'Rack::Attack.blacklist' is deprecated. Please use 'blocklist' instead."
57
- blocklist(name, &block)
57
+ anonymous_safelists << Safelist.new { |request| IPAddr.new(ip_address).include?(IPAddr.new(request.ip)) }
58
58
  end
59
59
 
60
60
  def throttle(name, options, &block)
61
- self.throttles[name] = Throttle.new(name, options, block)
61
+ throttles[name] = Throttle.new(name, options, &block)
62
62
  end
63
63
 
64
64
  def track(name, options = {}, &block)
65
- self.tracks[name] = Track.new(name, options, block)
65
+ tracks[name] = Track.new(name, options, &block)
66
66
  end
67
67
 
68
- def safelists; @safelists ||= {}; end
69
-
70
- def blocklists; @blocklists ||= {}; end
71
-
72
- def throttles; @throttles ||= {}; end
68
+ def safelists
69
+ @safelists ||= {}
70
+ end
73
71
 
74
- def tracks; @tracks ||= {}; end
72
+ def blocklists
73
+ @blocklists ||= {}
74
+ end
75
75
 
76
- def whitelists
77
- warn "[DEPRECATION] 'Rack::Attack.whitelists' is deprecated. Please use 'safelists' instead."
78
- safelists
76
+ def throttles
77
+ @throttles ||= {}
79
78
  end
80
79
 
81
- def blacklists
82
- warn "[DEPRECATION] 'Rack::Attack.blacklists' is deprecated. Please use 'blocklists' instead."
83
- blocklists
80
+ def tracks
81
+ @tracks ||= {}
84
82
  end
85
83
 
86
84
  def safelisted?(request)
87
- ip_safelists.any? { |safelist| safelist.matched_by?(request) } ||
85
+ anonymous_safelists.any? { |safelist| safelist.matched_by?(request) } ||
88
86
  safelists.any? { |_name, safelist| safelist.matched_by?(request) }
89
87
  end
90
88
 
91
- def whitelisted?(request)
92
- warn "[DEPRECATION] 'Rack::Attack.whitelisted?' is deprecated. Please use 'safelisted?' instead."
93
- safelisted?(request)
94
- end
95
-
96
89
  def blocklisted?(request)
97
- ip_blocklists.any? { |blocklist| blocklist.matched_by?(request) } ||
90
+ anonymous_blocklists.any? { |blocklist| blocklist.matched_by?(request) } ||
98
91
  blocklists.any? { |_name, blocklist| blocklist.matched_by?(request) }
99
92
  end
100
93
 
101
- def blacklisted?(request)
102
- warn "[DEPRECATION] 'Rack::Attack.blacklisted?' is deprecated. Please use 'blocklisted?' instead."
103
- blocklisted?(request)
104
- end
105
-
106
94
  def throttled?(request)
107
95
  throttles.any? do |_name, throttle|
108
96
  throttle.matched_by?(request)
@@ -116,7 +104,13 @@ class Rack::Attack
116
104
  end
117
105
 
118
106
  def instrument(request)
119
- notifier.instrument('rack.attack', request) if notifier
107
+ if notifier
108
+ event_type = request.env["rack.attack.match_type"]
109
+ notifier.instrument("#{event_type}.rack_attack", request: request)
110
+
111
+ # Deprecated: Keeping just for backwards compatibility
112
+ notifier.instrument("rack.attack", request: request)
113
+ end
120
114
  end
121
115
 
122
116
  def cache
@@ -125,37 +119,19 @@ class Rack::Attack
125
119
 
126
120
  def clear_configuration
127
121
  @safelists, @blocklists, @throttles, @tracks = {}, {}, {}, {}
128
- @ip_blocklists = []
129
- @ip_safelists = []
122
+ self.anonymous_blocklists = []
123
+ self.anonymous_safelists = []
130
124
  end
131
125
 
132
126
  def clear!
133
127
  warn "[DEPRECATION] Rack::Attack.clear! is deprecated. Please use Rack::Attack.clear_configuration instead"
134
128
  clear_configuration
135
129
  end
136
-
137
- def blacklisted_response=(res)
138
- warn "[DEPRECATION] 'Rack::Attack.blacklisted_response=' is deprecated. Please use 'blocklisted_response=' instead."
139
- self.blocklisted_response = res
140
- end
141
-
142
- def blacklisted_response
143
- warn "[DEPRECATION] 'Rack::Attack.blacklisted_response' is deprecated. Please use 'blocklisted_response' instead."
144
- blocklisted_response
145
- end
146
-
147
- private
148
-
149
- def ip_blocklists
150
- @ip_blocklists ||= []
151
- end
152
-
153
- def ip_safelists
154
- @ip_safelists ||= []
155
- end
156
130
  end
157
131
 
158
132
  # Set defaults
133
+ @anonymous_blocklists = []
134
+ @anonymous_safelists = []
159
135
  @notifier = ActiveSupport::Notifications if defined?(ActiveSupport::Notifications)
160
136
  @blocklisted_response = lambda { |_env| [403, { 'Content-Type' => 'text/plain' }, ["Forbidden\n"]] }
161
137
  @throttled_response = lambda { |env|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rack
2
4
  class Attack
3
5
  class Allow2Ban < Fail2Ban
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rack
2
4
  class Attack
3
5
  class Blocklist < Check
4
- def initialize(name, block)
6
+ def initialize(name = nil, &block)
5
7
  super
6
8
  @type = :blocklist
7
9
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rack
2
4
  class Attack
3
5
  class Cache
@@ -27,7 +29,7 @@ module Rack
27
29
  end
28
30
 
29
31
  def write(unprefixed_key, value, expires_in)
30
- store.write("#{prefix}:#{unprefixed_key}", value, :expires_in => expires_in)
32
+ store.write("#{prefix}:#{unprefixed_key}", value, expires_in: expires_in)
31
33
  end
32
34
 
33
35
  def reset_count(unprefixed_key, period)
@@ -52,13 +54,13 @@ module Rack
52
54
  enforce_store_presence!
53
55
  enforce_store_method_presence!(:increment)
54
56
 
55
- result = store.increment(key, 1, :expires_in => expires_in)
57
+ result = store.increment(key, 1, expires_in: expires_in)
56
58
 
57
59
  # NB: Some stores return nil when incrementing uninitialized values
58
60
  if result.nil?
59
61
  enforce_store_method_presence!(:write)
60
62
 
61
- store.write(key, 1, :expires_in => expires_in)
63
+ store.write(key, 1, expires_in: expires_in)
62
64
  end
63
65
  result || 1
64
66
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rack
2
4
  class Attack
3
5
  class Check
4
6
  attr_reader :name, :block, :type
5
- def initialize(name, options = {}, block)
7
+ def initialize(name, options = {}, &block)
6
8
  @name, @block = name, block
7
9
  @type = options.fetch(:type, nil)
8
10
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rack
2
4
  class Attack
3
5
  class Fail2Ban