rack-attack 3.0.0 → 4.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.
Potentially problematic release.
This version of rack-attack might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +15 -4
- data/lib/rack/attack.rb +48 -39
- data/lib/rack/attack/allow2ban.rb +1 -1
- data/lib/rack/attack/blacklist.rb +1 -1
- data/lib/rack/attack/cache.rb +1 -1
- data/lib/rack/attack/check.rb +1 -1
- data/lib/rack/attack/fail2ban.rb +1 -1
- data/lib/rack/attack/request.rb +6 -0
- data/lib/rack/attack/store_proxy.rb +7 -42
- data/lib/rack/attack/store_proxy/dalli_proxy.rb +65 -0
- data/lib/rack/attack/store_proxy/redis_store_proxy.rb +42 -0
- data/lib/rack/attack/throttle.rb +1 -1
- data/lib/rack/attack/track.rb +1 -1
- data/lib/rack/attack/version.rb +2 -2
- data/lib/rack/attack/whitelist.rb +1 -1
- data/spec/integration/offline_spec.rb +47 -0
- data/spec/integration/rack_attack_cache_spec.rb +6 -31
- data/spec/rack_attack_dalli_proxy_spec.rb +10 -0
- data/spec/rack_attack_request_spec.rb +19 -0
- data/spec/spec_helper.rb +4 -0
- metadata +39 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ff9b10f54b7093a546fea83332521abbd15b50fc
|
4
|
+
data.tar.gz: 766a4136c3895f45c09288e9fc97fe4a5e8e596c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d5891f076087208013f1df9942977692aec45692ac6ec6fea1d143731033bebeed08d955a977ac7322aed8c9390383557214891ea61344351b1d1ec04c5f897e
|
7
|
+
data.tar.gz: d6e5098b06db042fb7e863b7d34668d4f5bff12812d7ee1d7493455ca8546606605431ebd403041442ee82f47509ad8c2365a2a2bcd130706c3a328a74dc94ed
|
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# Rack::Attack!!!
|
2
|
-
*
|
2
|
+
*Rack middleware for blocking & throttling abusive requests*
|
3
3
|
|
4
4
|
Rack::Attack is a rack middleware to protect your web app from bad clients.
|
5
5
|
It allows *whitelisting*, *blacklisting*, *throttling*, and *tracking* based on arbitrary properties of the request.
|
@@ -13,7 +13,7 @@ See the [Backing & Hacking blog post](http://www.kickstarter.com/backing-and-hac
|
|
13
13
|
[](https://codeclimate.com/github/kickstarter/rack-attack)
|
14
14
|
|
15
15
|
|
16
|
-
##
|
16
|
+
## Getting started
|
17
17
|
|
18
18
|
Install the [rack-attack](http://rubygems.org/gems/rack-attack) gem; or add it to you Gemfile with bundler:
|
19
19
|
|
@@ -36,6 +36,17 @@ Or for Rackup files:
|
|
36
36
|
use Rack::Attack
|
37
37
|
```
|
38
38
|
|
39
|
+
Add a `rack-attack.rb` file to `config/initalizers/`:
|
40
|
+
```ruby
|
41
|
+
# In config/initializers/rack-attack.rb
|
42
|
+
module Rack::Attack
|
43
|
+
# your custom configuration...
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
*Tip:* The example in the wiki is a great way to get started:
|
48
|
+
[Example Configuration](https://github.com/kickstarter/rack-attack/wiki/Example-Configuration)
|
49
|
+
|
39
50
|
Optionally configure the cache store for throttling:
|
40
51
|
|
41
52
|
```ruby
|
@@ -271,6 +282,6 @@ New releases of Rack::Attack are announced on
|
|
271
282
|
|
272
283
|
## License
|
273
284
|
|
274
|
-
Copyright
|
285
|
+
Copyright Kickstarter, Inc.
|
275
286
|
|
276
|
-
Released under an [MIT License](http://opensource.org/licenses/MIT)
|
287
|
+
Released under an [MIT License](http://opensource.org/licenses/MIT).
|
data/lib/rack/attack.rb
CHANGED
@@ -1,14 +1,19 @@
|
|
1
1
|
require 'rack'
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
autoload :
|
6
|
-
autoload :
|
7
|
-
autoload :
|
8
|
-
autoload :
|
9
|
-
autoload :
|
10
|
-
autoload :
|
11
|
-
autoload :
|
2
|
+
require 'forwardable'
|
3
|
+
|
4
|
+
class Rack::Attack
|
5
|
+
autoload :Cache, 'rack/attack/cache'
|
6
|
+
autoload :Check, 'rack/attack/check'
|
7
|
+
autoload :Throttle, 'rack/attack/throttle'
|
8
|
+
autoload :Whitelist, 'rack/attack/whitelist'
|
9
|
+
autoload :Blacklist, 'rack/attack/blacklist'
|
10
|
+
autoload :Track, 'rack/attack/track'
|
11
|
+
autoload :StoreProxy, 'rack/attack/store_proxy'
|
12
|
+
autoload :DalliProxy, 'rack/attack/store_proxy/dalli_proxy'
|
13
|
+
autoload :RedisStoreProxy, 'rack/attack/store_proxy/redis_store_proxy'
|
14
|
+
autoload :Fail2Ban, 'rack/attack/fail2ban'
|
15
|
+
autoload :Allow2Ban, 'rack/attack/allow2ban'
|
16
|
+
autoload :Request, 'rack/attack/request'
|
12
17
|
|
13
18
|
class << self
|
14
19
|
|
@@ -35,35 +40,6 @@ module Rack::Attack
|
|
35
40
|
def throttles; @throttles ||= {}; end
|
36
41
|
def tracks; @tracks ||= {}; end
|
37
42
|
|
38
|
-
def new(app)
|
39
|
-
@app = app
|
40
|
-
|
41
|
-
# Set defaults
|
42
|
-
@notifier ||= ActiveSupport::Notifications if defined?(ActiveSupport::Notifications)
|
43
|
-
@blacklisted_response ||= lambda {|env| [403, {}, ["Forbidden\n"]] }
|
44
|
-
@throttled_response ||= lambda {|env|
|
45
|
-
retry_after = env['rack.attack.match_data'][:period] rescue nil
|
46
|
-
[429, {'Retry-After' => retry_after.to_s}, ["Retry later\n"]]
|
47
|
-
}
|
48
|
-
|
49
|
-
self
|
50
|
-
end
|
51
|
-
|
52
|
-
def call(env)
|
53
|
-
req = Rack::Request.new(env)
|
54
|
-
|
55
|
-
if whitelisted?(req)
|
56
|
-
@app.call(env)
|
57
|
-
elsif blacklisted?(req)
|
58
|
-
blacklisted_response[env]
|
59
|
-
elsif throttled?(req)
|
60
|
-
throttled_response[env]
|
61
|
-
else
|
62
|
-
tracked?(req)
|
63
|
-
@app.call(env)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
43
|
def whitelisted?(req)
|
68
44
|
whitelists.any? do |name, whitelist|
|
69
45
|
whitelist[req]
|
@@ -101,4 +77,37 @@ module Rack::Attack
|
|
101
77
|
end
|
102
78
|
|
103
79
|
end
|
80
|
+
|
81
|
+
# Set defaults
|
82
|
+
@notifier = ActiveSupport::Notifications if defined?(ActiveSupport::Notifications)
|
83
|
+
@blacklisted_response = lambda {|env| [403, {}, ["Forbidden\n"]] }
|
84
|
+
@throttled_response = lambda {|env|
|
85
|
+
retry_after = env['rack.attack.match_data'][:period] rescue nil
|
86
|
+
[429, {'Retry-After' => retry_after.to_s}, ["Retry later\n"]]
|
87
|
+
}
|
88
|
+
|
89
|
+
def initialize(app)
|
90
|
+
@app = app
|
91
|
+
end
|
92
|
+
|
93
|
+
def call(env)
|
94
|
+
req = Rack::Attack::Request.new(env)
|
95
|
+
|
96
|
+
if whitelisted?(req)
|
97
|
+
@app.call(env)
|
98
|
+
elsif blacklisted?(req)
|
99
|
+
self.class.blacklisted_response[env]
|
100
|
+
elsif throttled?(req)
|
101
|
+
self.class.throttled_response[env]
|
102
|
+
else
|
103
|
+
tracked?(req)
|
104
|
+
@app.call(env)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
extend Forwardable
|
109
|
+
def_delegators self, :whitelisted?,
|
110
|
+
:blacklisted?,
|
111
|
+
:throttled?,
|
112
|
+
:tracked?
|
104
113
|
end
|
data/lib/rack/attack/cache.rb
CHANGED
data/lib/rack/attack/check.rb
CHANGED
data/lib/rack/attack/fail2ban.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
require 'delegate'
|
2
|
-
|
3
1
|
module Rack
|
4
|
-
|
5
|
-
|
2
|
+
class Attack
|
3
|
+
module StoreProxy
|
4
|
+
PROXIES = [DalliProxy, RedisStoreProxy]
|
5
|
+
|
6
6
|
def self.build(store)
|
7
7
|
# RedisStore#increment needs different behavior, so detect that
|
8
8
|
# (method has an arity of 2; must call #expire separately
|
@@ -12,46 +12,11 @@ module Rack
|
|
12
12
|
store = store.instance_variable_get(:@data)
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
RedisStoreProxy.new(store)
|
17
|
-
else
|
18
|
-
store
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
class RedisStoreProxy < SimpleDelegator
|
23
|
-
def initialize(store)
|
24
|
-
super(store)
|
25
|
-
end
|
26
|
-
|
27
|
-
def read(key)
|
28
|
-
self.get(key)
|
29
|
-
rescue Redis::BaseError
|
30
|
-
nil
|
31
|
-
end
|
32
|
-
|
33
|
-
def write(key, value, options={})
|
34
|
-
if (expires_in = options[:expires_in])
|
35
|
-
self.setex(key, expires_in, value)
|
36
|
-
else
|
37
|
-
self.set(key, value)
|
38
|
-
end
|
39
|
-
rescue Redis::BaseError
|
40
|
-
nil
|
41
|
-
end
|
42
|
-
|
43
|
-
def increment(key, amount, options={})
|
44
|
-
count = nil
|
45
|
-
self.pipelined do
|
46
|
-
count = self.incrby(key, amount)
|
47
|
-
self.expire(key, options[:expires_in]) if options[:expires_in]
|
48
|
-
end
|
49
|
-
count.value if count
|
50
|
-
rescue Redis::BaseError
|
51
|
-
nil
|
52
|
-
end
|
15
|
+
klass = PROXIES.find { |proxy| proxy.handle?(store) }
|
53
16
|
|
17
|
+
klass ? klass.new(store) : store
|
54
18
|
end
|
19
|
+
|
55
20
|
end
|
56
21
|
end
|
57
22
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
class Attack
|
5
|
+
module StoreProxy
|
6
|
+
class DalliProxy < SimpleDelegator
|
7
|
+
def self.handle?(store)
|
8
|
+
return false unless defined?(::Dalli)
|
9
|
+
|
10
|
+
# Consider extracting to a separate Connection Pool proxy to reduce
|
11
|
+
# code here and handle clients other than Dalli.
|
12
|
+
if defined?(::ConnectionPool) && store.is_a?(::ConnectionPool)
|
13
|
+
store.with { |conn| conn.is_a?(::Dalli::Client) }
|
14
|
+
else
|
15
|
+
store.is_a?(::Dalli::Client)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(client)
|
20
|
+
super(client)
|
21
|
+
stub_with_if_missing
|
22
|
+
end
|
23
|
+
|
24
|
+
def read(key)
|
25
|
+
with do |client|
|
26
|
+
client.get(key)
|
27
|
+
end
|
28
|
+
rescue Dalli::DalliError
|
29
|
+
end
|
30
|
+
|
31
|
+
def write(key, value, options={})
|
32
|
+
with do |client|
|
33
|
+
client.set(key, value, options.fetch(:expires_in, 0), raw: true)
|
34
|
+
end
|
35
|
+
rescue Dalli::DalliError
|
36
|
+
end
|
37
|
+
|
38
|
+
def increment(key, amount, options={})
|
39
|
+
with do |client|
|
40
|
+
client.incr(key, amount, options.fetch(:expires_in, 0), amount)
|
41
|
+
end
|
42
|
+
rescue Dalli::DalliError
|
43
|
+
end
|
44
|
+
|
45
|
+
def delete(key)
|
46
|
+
with do |client|
|
47
|
+
client.delete(key)
|
48
|
+
end
|
49
|
+
rescue Dalli::DalliError
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def stub_with_if_missing
|
55
|
+
unless __getobj__.respond_to?(:with)
|
56
|
+
class << self
|
57
|
+
def with; yield __getobj__; end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
class Attack
|
5
|
+
module StoreProxy
|
6
|
+
class RedisStoreProxy < SimpleDelegator
|
7
|
+
def self.handle?(store)
|
8
|
+
defined?(::Redis::Store) && store.is_a?(::Redis::Store)
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(store)
|
12
|
+
super(store)
|
13
|
+
end
|
14
|
+
|
15
|
+
def read(key)
|
16
|
+
self.get(key)
|
17
|
+
rescue Redis::BaseError
|
18
|
+
end
|
19
|
+
|
20
|
+
def write(key, value, options={})
|
21
|
+
if (expires_in = options[:expires_in])
|
22
|
+
self.setex(key, expires_in, value)
|
23
|
+
else
|
24
|
+
self.set(key, value)
|
25
|
+
end
|
26
|
+
rescue Redis::BaseError
|
27
|
+
end
|
28
|
+
|
29
|
+
def increment(key, amount, options={})
|
30
|
+
count = nil
|
31
|
+
self.pipelined do
|
32
|
+
count = self.incrby(key, amount)
|
33
|
+
self.expire(key, options[:expires_in]) if options[:expires_in]
|
34
|
+
end
|
35
|
+
count.value if count
|
36
|
+
rescue Redis::BaseError
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/rack/attack/throttle.rb
CHANGED
data/lib/rack/attack/track.rb
CHANGED
data/lib/rack/attack/version.rb
CHANGED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'active_support/cache'
|
2
|
+
require 'active_support/cache/redis_store'
|
3
|
+
require 'dalli'
|
4
|
+
require_relative '../spec_helper'
|
5
|
+
|
6
|
+
OfflineExamples = Minitest::SharedExamples.new do
|
7
|
+
|
8
|
+
it 'should write' do
|
9
|
+
@cache.write('cache-test-key', 'foobar', 1)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should read' do
|
13
|
+
@cache.read('cache-test-key')
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should count' do
|
17
|
+
@cache.send(:do_count, 'rack::attack::cache-test-key', 1)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'when Redis is offline' do
|
23
|
+
include OfflineExamples
|
24
|
+
|
25
|
+
before {
|
26
|
+
@cache = Rack::Attack::Cache.new
|
27
|
+
# Use presumably unused port for Redis client
|
28
|
+
@cache.store = ActiveSupport::Cache::RedisStore.new(:host => '127.0.0.1', :port => 3333)
|
29
|
+
}
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
describe 'when Memcached is offline' do
|
34
|
+
include OfflineExamples
|
35
|
+
|
36
|
+
before {
|
37
|
+
Dalli.logger.level = Logger::FATAL
|
38
|
+
|
39
|
+
@cache = Rack::Attack::Cache.new
|
40
|
+
@cache.store = Dalli::Client.new('127.0.0.1:22122')
|
41
|
+
}
|
42
|
+
|
43
|
+
after {
|
44
|
+
Dalli.logger.level = Logger::INFO
|
45
|
+
}
|
46
|
+
|
47
|
+
end
|
@@ -15,10 +15,13 @@ describe Rack::Attack::Cache do
|
|
15
15
|
|
16
16
|
require 'active_support/cache/dalli_store'
|
17
17
|
require 'active_support/cache/redis_store'
|
18
|
+
require 'connection_pool'
|
18
19
|
cache_stores = [
|
19
20
|
ActiveSupport::Cache::MemoryStore.new,
|
20
|
-
ActiveSupport::Cache::DalliStore.new("
|
21
|
-
ActiveSupport::Cache::RedisStore.new("
|
21
|
+
ActiveSupport::Cache::DalliStore.new("127.0.0.1"),
|
22
|
+
ActiveSupport::Cache::RedisStore.new("127.0.0.1"),
|
23
|
+
Dalli::Client.new,
|
24
|
+
ConnectionPool.new { Dalli::Client.new },
|
22
25
|
Redis::Store.new
|
23
26
|
]
|
24
27
|
|
@@ -27,7 +30,7 @@ describe Rack::Attack::Cache do
|
|
27
30
|
describe "with #{store.class}" do
|
28
31
|
|
29
32
|
before {
|
30
|
-
@cache
|
33
|
+
@cache = Rack::Attack::Cache.new
|
31
34
|
@key = "rack::attack:cache-test-key"
|
32
35
|
@expires_in = 1
|
33
36
|
@cache.store = store
|
@@ -80,32 +83,4 @@ describe Rack::Attack::Cache do
|
|
80
83
|
end
|
81
84
|
|
82
85
|
end
|
83
|
-
|
84
|
-
describe "should not error if redis is not running" do
|
85
|
-
before {
|
86
|
-
@cache = Rack::Attack::Cache.new
|
87
|
-
@key = "rack::attack:cache-test-key"
|
88
|
-
@expires_in = 1
|
89
|
-
# Use presumably unused port for Redis client
|
90
|
-
@cache.store = ActiveSupport::Cache::RedisStore.new(:host => '127.0.0.1', :port => 3333)
|
91
|
-
}
|
92
|
-
describe "write" do
|
93
|
-
it "should not raise exception" do
|
94
|
-
@cache.write("cache-test-key", "foobar", 1)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
describe "read" do
|
99
|
-
it "should not raise exception" do
|
100
|
-
@cache.read("cache-test-key")
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
describe "do_count" do
|
105
|
-
it "should not raise exception" do
|
106
|
-
@cache.send(:do_count, @key, @expires_in)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
86
|
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe Rack::Attack::StoreProxy::DalliProxy do
|
4
|
+
|
5
|
+
it 'should stub Dalli::Client#with on older clients' do
|
6
|
+
proxy = Rack::Attack::StoreProxy::DalliProxy.new(Class.new)
|
7
|
+
proxy.with {} # will not raise an error
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Rack::Attack' do
|
4
|
+
describe 'helpers' do
|
5
|
+
before do
|
6
|
+
class Rack::Attack::Request
|
7
|
+
def remote_ip
|
8
|
+
ip
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
Rack::Attack.whitelist('valid IP') do |req|
|
13
|
+
req.remote_ip == "127.0.0.1"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
allow_ok_requests
|
18
|
+
end
|
19
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-attack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Suggs
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-04-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: appraisal
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: activesupport
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,6 +122,20 @@ dependencies:
|
|
108
122
|
- - ">="
|
109
123
|
- !ruby/object:Gem::Version
|
110
124
|
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: connection_pool
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
111
139
|
description: A rack middleware for throttling and blocking abusive requests
|
112
140
|
email: aaron@ktheory.com
|
113
141
|
executables: []
|
@@ -122,14 +150,20 @@ files:
|
|
122
150
|
- lib/rack/attack/cache.rb
|
123
151
|
- lib/rack/attack/check.rb
|
124
152
|
- lib/rack/attack/fail2ban.rb
|
153
|
+
- lib/rack/attack/request.rb
|
125
154
|
- lib/rack/attack/store_proxy.rb
|
155
|
+
- lib/rack/attack/store_proxy/dalli_proxy.rb
|
156
|
+
- lib/rack/attack/store_proxy/redis_store_proxy.rb
|
126
157
|
- lib/rack/attack/throttle.rb
|
127
158
|
- lib/rack/attack/track.rb
|
128
159
|
- lib/rack/attack/version.rb
|
129
160
|
- lib/rack/attack/whitelist.rb
|
130
161
|
- spec/allow2ban_spec.rb
|
131
162
|
- spec/fail2ban_spec.rb
|
163
|
+
- spec/integration/offline_spec.rb
|
132
164
|
- spec/integration/rack_attack_cache_spec.rb
|
165
|
+
- spec/rack_attack_dalli_proxy_spec.rb
|
166
|
+
- spec/rack_attack_request_spec.rb
|
133
167
|
- spec/rack_attack_spec.rb
|
134
168
|
- spec/rack_attack_throttle_spec.rb
|
135
169
|
- spec/rack_attack_track_spec.rb
|
@@ -162,7 +196,10 @@ summary: Block & throttle abusive requests
|
|
162
196
|
test_files:
|
163
197
|
- spec/allow2ban_spec.rb
|
164
198
|
- spec/fail2ban_spec.rb
|
199
|
+
- spec/integration/offline_spec.rb
|
165
200
|
- spec/integration/rack_attack_cache_spec.rb
|
201
|
+
- spec/rack_attack_dalli_proxy_spec.rb
|
202
|
+
- spec/rack_attack_request_spec.rb
|
166
203
|
- spec/rack_attack_spec.rb
|
167
204
|
- spec/rack_attack_throttle_spec.rb
|
168
205
|
- spec/rack_attack_track_spec.rb
|