Change object type yielded to ActiveSupport::Subscribers

https://github.com/kickstarter/rack-attack/issues/255

Change the object type from instances of type Rack::Attack::Request to
instances of type Hash. (`req` becomes `request: req`).
This commit is contained in:
Domenoth 2018-01-11 17:42:17 -08:00
parent 8b4f27827d
commit 5004b04ac7
5 changed files with 42 additions and 10 deletions

View file

@ -215,7 +215,8 @@ Rack::Attack.track("special_agent", limit: 6, period: 60) do |req|
end
# Track it using ActiveSupport::Notification
ActiveSupport::Notifications.subscribe("rack.attack") do |name, start, finish, request_id, req|
ActiveSupport::Notifications.subscribe("rack.attack") do |name, start, finish, request_id, payload|
req = payload[:request]
if req.env['rack.attack.matched'] == "special_agent" && req.env['rack.attack.match_type'] == :track
Rails.logger.info "special_agent: #{req.path}"
STATSD.increment("special_agent")
@ -283,8 +284,8 @@ Rack::Attack uses the [ActiveSupport::Notifications](http://api.rubyonrails.org/
You can subscribe to 'rack.attack' events and log it, graph it, etc:
```ruby
ActiveSupport::Notifications.subscribe('rack.attack') do |name, start, finish, request_id, req|
puts req.inspect
ActiveSupport::Notifications.subscribe('rack.attack') do |name, start, finish, request_id, payload|
puts payload[:request].inspect
end
```

View file

@ -100,7 +100,7 @@ class Rack::Attack
end
def instrument(req)
notifier.instrument('rack.attack', req) if notifier
notifier.instrument('rack.attack', request: req) if notifier
end
def cache

View file

@ -9,9 +9,9 @@ describe "#track" do
notification_matched = nil
notification_type = nil
ActiveSupport::Notifications.subscribe("rack.attack") do |_name, _start, _finish, _id, request|
notification_matched = request.env["rack.attack.matched"]
notification_type = request.env["rack.attack.match_type"]
ActiveSupport::Notifications.subscribe("rack.attack") do |_name, _start, _finish, _id, payload|
notification_matched = payload[:request].env["rack.attack.matched"]
notification_type = payload[:request].env["rack.attack.match_type"]
end
get "/", {}, "REMOTE_ADDR" => "5.6.7.8"

View file

@ -12,9 +12,9 @@ describe "#track with throttle-ish options" do
notification_matched = nil
notification_type = nil
ActiveSupport::Notifications.subscribe("rack.attack") do |_name, _start, _finish, _id, request|
notification_matched = request.env["rack.attack.matched"]
notification_type = request.env["rack.attack.match_type"]
ActiveSupport::Notifications.subscribe("rack.attack") do |_name, _start, _finish, _id, payload|
notification_matched = payload[:request].env["rack.attack.matched"]
notification_type = payload[:request].env["rack.attack.match_type"]
end
get "/", {}, "REMOTE_ADDR" => "1.2.3.4"

View file

@ -0,0 +1,31 @@
# ActiveSupport::Subscribers added in ~> 4.0.2.0
if ActiveSupport::VERSION::MAJOR > 3
require_relative 'spec_helper'
require 'active_support/subscriber'
class CustomSubscriber < ActiveSupport::Subscriber
def rack(event)
# Do virtually (but not) nothing.
event.inspect
end
end
describe 'Rack::Attack.instrument' do
before do
@period = 60 # Use a long period; failures due to cache key rotation less likely
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
Rack::Attack.throttle('ip/sec', limit: 1, period: @period) { |req| req.ip }
end
describe "with throttling" do
before do
ActiveSupport::Notifications.stub(:notifier, ActiveSupport::Notifications::Fanout.new) do
CustomSubscriber.attach_to("attack")
2.times { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' }
end
end
it 'should instrument without error' do
last_response.status.must_equal 429
end
end
end
end