mirror of
https://github.com/samsonjs/rack-attack.git
synced 2026-04-27 15:07:41 +00:00
Change instrumentation API for simpler notifications
This commit is contained in:
parent
9552d56c24
commit
ccdc1f993a
6 changed files with 25 additions and 14 deletions
10
README.md
10
README.md
|
|
@ -82,7 +82,11 @@ Note that `req` is a [Rack::Request](http://rack.rubyforge.org/doc/classes/Rack/
|
||||||
Customize the response of throttled requests using an object that adheres to the [Rack app interface](http://rack.rubyforge.org/doc/SPEC.html).
|
Customize the response of throttled requests using an object that adheres to the [Rack app interface](http://rack.rubyforge.org/doc/SPEC.html).
|
||||||
|
|
||||||
Rack:Attack.throttled_response = lambda do |env|
|
Rack:Attack.throttled_response = lambda do |env|
|
||||||
env['rack.attack.throttled'] # name and other data about the matched throttle
|
# name and other data about the matched throttle
|
||||||
|
env['rack.attack.matched']
|
||||||
|
env['rack.attack.match_type']
|
||||||
|
env['rack.attack.match_data']
|
||||||
|
|
||||||
[ 503, {}, ['Throttled']]
|
[ 503, {}, ['Throttled']]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -97,9 +101,9 @@ Similarly for blacklisted responses:
|
||||||
|
|
||||||
Rack::Attack uses the [ActiveSupport::Notifications](http://api.rubyonrails.org/classes/ActiveSupport/Notifications.html) API if available.
|
Rack::Attack uses the [ActiveSupport::Notifications](http://api.rubyonrails.org/classes/ActiveSupport/Notifications.html) API if available.
|
||||||
|
|
||||||
You can subscribe to 'rack.attack.{blacklist,throttle,whitelist}' events and log it, graph it, etc:
|
You can subscribe to 'rack.attack' events and log it, graph it, etc:
|
||||||
|
|
||||||
ActiveSupport::Notifications.subscribe('rack.attack.blacklist') do |name, start, finish, request_id, req|
|
ActiveSupport::Notifications.subscribe('rack.attack') do |name, start, finish, request_id, req|
|
||||||
puts req.inspect
|
puts req.inspect
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ module Rack::Attack
|
||||||
@notifier ||= ActiveSupport::Notifications if defined?(ActiveSupport::Notifications)
|
@notifier ||= ActiveSupport::Notifications if defined?(ActiveSupport::Notifications)
|
||||||
@blacklisted_response ||= lambda {|env| [503, {}, ['Blocked']] }
|
@blacklisted_response ||= lambda {|env| [503, {}, ['Blocked']] }
|
||||||
@throttled_response ||= lambda {|env|
|
@throttled_response ||= lambda {|env|
|
||||||
retry_after = env['rack.attack.matched'][:period] rescue nil
|
retry_after = env['rack.attack.match_data'][:period] rescue nil
|
||||||
[503, {'Retry-After' => retry_after}, ['Retry later']]
|
[503, {'Retry-After' => retry_after}, ['Retry later']]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,8 +75,8 @@ module Rack::Attack
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def instrument(type, payload)
|
def instrument(req)
|
||||||
notifier.instrument("rack.attack.#{type}", payload) if notifier
|
notifier.instrument('rack.attack', req) if notifier
|
||||||
end
|
end
|
||||||
|
|
||||||
def clear!
|
def clear!
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,9 @@ module Rack
|
||||||
def [](req)
|
def [](req)
|
||||||
block[req].tap {|match|
|
block[req].tap {|match|
|
||||||
if match
|
if match
|
||||||
req.env["rack.attack.matched"] = {type => name}
|
req.env["rack.attack.matched"] = name
|
||||||
Rack::Attack.instrument(type, req)
|
req.env["rack.attack.match_type"] = type
|
||||||
|
Rack::Attack.instrument(req)
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,10 @@ module Rack
|
||||||
count = cache.count(key, period)
|
count = cache.count(key, period)
|
||||||
(count > limit).tap do |throttled|
|
(count > limit).tap do |throttled|
|
||||||
if throttled
|
if throttled
|
||||||
req.env['rack.attack.matched'] = {:throttle => name, :count => count, :period => period, :limit => limit}
|
req.env['rack.attack.matched'] = name
|
||||||
Rack::Attack.instrument(:throttle, req)
|
req.env['rack.attack.match_type'] = :throttle
|
||||||
|
req.env['rack.attack.match_data'] = {:count => count, :period => period, :limit => limit}
|
||||||
|
Rack::Attack.instrument(req)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
module Rack
|
module Rack
|
||||||
module Attack
|
module Attack
|
||||||
VERSION = '0.1.0'
|
VERSION = '0.2.0'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,8 @@ describe 'Rack::Attack' do
|
||||||
last_response.status.must_equal 503
|
last_response.status.must_equal 503
|
||||||
end
|
end
|
||||||
it "should tag the env" do
|
it "should tag the env" do
|
||||||
last_request.env['rack.attack.matched'].must_equal({:blacklist => "ip #{@bad_ip}"})
|
last_request.env['rack.attack.matched'].must_equal "ip #{@bad_ip}"
|
||||||
|
last_request.env['rack.attack.match_type'].must_equal :blacklist
|
||||||
end
|
end
|
||||||
|
|
||||||
allow_ok_requests
|
allow_ok_requests
|
||||||
|
|
@ -57,7 +58,8 @@ describe 'Rack::Attack' do
|
||||||
last_response.status.must_equal 200
|
last_response.status.must_equal 200
|
||||||
end
|
end
|
||||||
it "should tag the env" do
|
it "should tag the env" do
|
||||||
last_request.env['rack.attack.matched'].must_equal({:whitelist => 'good ua'})
|
last_request.env['rack.attack.matched'].must_equal 'good ua'
|
||||||
|
last_request.env['rack.attack.match_type'].must_equal :whitelist
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -86,7 +88,9 @@ describe 'Rack::Attack' do
|
||||||
last_response.status.must_equal 503
|
last_response.status.must_equal 503
|
||||||
end
|
end
|
||||||
it 'should tag the env' do
|
it 'should tag the env' do
|
||||||
last_request.env['rack.attack.matched'].must_equal({:throttle => 'ip/sec', :count => 2, :limit => 1, :period => 1})
|
last_request.env['rack.attack.matched'].must_equal 'ip/sec'
|
||||||
|
last_request.env['rack.attack.match_type'].must_equal :throttle
|
||||||
|
last_request.env['rack.attack.match_data'].must_equal({:count => 2, :limit => 1, :period => 1})
|
||||||
end
|
end
|
||||||
it 'should set a Retry-After header' do
|
it 'should set a Retry-After header' do
|
||||||
last_response.headers['Retry-After'].must_equal 1
|
last_response.headers['Retry-After'].must_equal 1
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue