rack-attack 5.4.2 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![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
|
-
###
|
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
|