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.
- checksums.yaml +4 -4
- data/README.md +65 -23
- data/Rakefile +3 -1
- data/lib/rack/attack.rb +46 -70
- data/lib/rack/attack/allow2ban.rb +2 -0
- data/lib/rack/attack/blocklist.rb +3 -1
- data/lib/rack/attack/cache.rb +5 -3
- data/lib/rack/attack/check.rb +3 -1
- data/lib/rack/attack/fail2ban.rb +2 -0
- data/lib/rack/attack/path_normalizer.rb +2 -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 -14
- data/lib/rack/attack/store_proxy/active_support_redis_store_proxy.rb +37 -0
- data/lib/rack/attack/store_proxy/dalli_proxy.rb +27 -13
- data/lib/rack/attack/store_proxy/redis_cache_store_proxy.rb +2 -4
- 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 +8 -6
- data/lib/rack/attack/track.rb +5 -3
- 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 +8 -12
- data/spec/acceptance/cache_store_config_for_fail2ban_spec.rb +8 -12
- 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/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 +2 -0
- data/spec/acceptance/stores/active_support_mem_cache_store_spec.rb +2 -0
- data/spec/acceptance/stores/active_support_memory_store_spec.rb +2 -0
- data/spec/acceptance/stores/active_support_redis_cache_store_pooled_spec.rb +2 -0
- data/spec/acceptance/stores/active_support_redis_cache_store_spec.rb +2 -0
- data/spec/acceptance/stores/active_support_redis_store_spec.rb +3 -1
- data/spec/acceptance/stores/connection_pool_dalli_client_spec.rb +2 -0
- data/spec/acceptance/stores/dalli_client_spec.rb +2 -0
- data/spec/acceptance/stores/redis_store_spec.rb +2 -0
- 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 +3 -1
- data/spec/fail2ban_spec.rb +3 -1
- 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 +2 -0
- data/spec/rack_attack_request_spec.rb +2 -0
- data/spec/rack_attack_spec.rb +2 -21
- data/spec/rack_attack_throttle_spec.rb +10 -8
- data/spec/rack_attack_track_spec.rb +4 -2
- data/spec/spec_helper.rb +5 -4
- data/spec/support/cache_store_helper.rb +2 -0
- metadata +21 -14
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f85825803ce676e10466175d4bb99cc151d649130d6f4008bdffdc1381b4650a
|
4
|
+
data.tar.gz: 2bcd9d6a9d75491df5a9ddf2f7a5128eae152245fce8f27a069f36037ebc8ddb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
[](https://travis-ci.org/kickstarter/rack-attack)
|
11
11
|
[](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
|
-
###
|
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
|
-
###
|
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:*
|
59
|
-
[
|
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
|
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,
|
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
|
-
###
|
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 `
|
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
|
-
'
|
311
|
-
'
|
312
|
-
'
|
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
|
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(
|
334
|
-
|
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](
|
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](
|
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 :
|
29
|
+
task default: [:rubocop, :test]
|
data/lib/rack/attack.rb
CHANGED
@@ -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
|
-
|
32
|
-
end
|
32
|
+
def safelist(name = nil, &block)
|
33
|
+
safelist = Safelist.new(name, &block)
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
61
|
+
throttles[name] = Throttle.new(name, options, &block)
|
62
62
|
end
|
63
63
|
|
64
64
|
def track(name, options = {}, &block)
|
65
|
-
|
65
|
+
tracks[name] = Track.new(name, options, &block)
|
66
66
|
end
|
67
67
|
|
68
|
-
def safelists
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
def throttles; @throttles ||= {}; end
|
68
|
+
def safelists
|
69
|
+
@safelists ||= {}
|
70
|
+
end
|
73
71
|
|
74
|
-
def
|
72
|
+
def blocklists
|
73
|
+
@blocklists ||= {}
|
74
|
+
end
|
75
75
|
|
76
|
-
def
|
77
|
-
|
78
|
-
safelists
|
76
|
+
def throttles
|
77
|
+
@throttles ||= {}
|
79
78
|
end
|
80
79
|
|
81
|
-
def
|
82
|
-
|
83
|
-
blocklists
|
80
|
+
def tracks
|
81
|
+
@tracks ||= {}
|
84
82
|
end
|
85
83
|
|
86
84
|
def safelisted?(request)
|
87
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
129
|
-
|
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|
|
data/lib/rack/attack/cache.rb
CHANGED
@@ -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, :
|
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, :
|
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, :
|
63
|
+
store.write(key, 1, expires_in: expires_in)
|
62
64
|
end
|
63
65
|
result || 1
|
64
66
|
end
|
data/lib/rack/attack/check.rb
CHANGED
@@ -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
|