Merge branch 'master' into patch-3

This commit is contained in:
hakanensari 2014-04-09 12:17:10 +01:00
commit 937cd3ca20
14 changed files with 76 additions and 42 deletions

View file

@ -2,6 +2,8 @@
## master (unreleased)
* Implement proxy for Dalli with better Memcachier support. (thanks @hakanensari)
* Rack::Attack.new returns an instance to ease testing (thanks @stevehodgkiss)
* Use Rack::Attack::Request subclass of Rack::Request for easier extending (thanks @tristandunn)
## v3.0.0 - 15 March 2014
* Change default blacklisted response to 403 Forbidden (thanks @carpodaster).

View file

@ -1,5 +1,7 @@
require 'rack'
module Rack::Attack
require 'forwardable'
class Rack::Attack
autoload :Cache, 'rack/attack/cache'
autoload :Check, 'rack/attack/check'
autoload :Throttle, 'rack/attack/throttle'
@ -8,7 +10,8 @@ module Rack::Attack
autoload :Track, 'rack/attack/track'
autoload :StoreProxy,'rack/attack/store_proxy'
autoload :Fail2Ban, 'rack/attack/fail2ban'
autoload :Allow2Ban, 'rack/attack/allow2ban'
autoload :Allow2Ban, 'rack/attack/allow2ban'
autoload :Request, 'rack/attack/request'
class << self
@ -35,35 +38,6 @@ module Rack::Attack
def throttles; @throttles ||= {}; end
def tracks; @tracks ||= {}; end
def new(app)
@app = app
# Set defaults
@notifier ||= ActiveSupport::Notifications if defined?(ActiveSupport::Notifications)
@blacklisted_response ||= lambda {|env| [403, {}, ["Forbidden\n"]] }
@throttled_response ||= lambda {|env|
retry_after = env['rack.attack.match_data'][:period] rescue nil
[429, {'Retry-After' => retry_after.to_s}, ["Retry later\n"]]
}
self
end
def call(env)
req = Rack::Request.new(env)
if whitelisted?(req)
@app.call(env)
elsif blacklisted?(req)
blacklisted_response[env]
elsif throttled?(req)
throttled_response[env]
else
tracked?(req)
@app.call(env)
end
end
def whitelisted?(req)
whitelists.any? do |name, whitelist|
whitelist[req]
@ -101,4 +75,37 @@ module Rack::Attack
end
end
# Set defaults
@notifier = ActiveSupport::Notifications if defined?(ActiveSupport::Notifications)
@blacklisted_response = lambda {|env| [403, {}, ["Forbidden\n"]] }
@throttled_response = lambda {|env|
retry_after = env['rack.attack.match_data'][:period] rescue nil
[429, {'Retry-After' => retry_after.to_s}, ["Retry later\n"]]
}
def initialize(app)
@app = app
end
def call(env)
req = Rack::Attack::Request.new(env)
if whitelisted?(req)
@app.call(env)
elsif blacklisted?(req)
self.class.blacklisted_response[env]
elsif throttled?(req)
self.class.throttled_response[env]
else
tracked?(req)
@app.call(env)
end
end
extend Forwardable
def_delegators self, :whitelisted?,
:blacklisted?,
:throttled?,
:tracked?
end

View file

@ -1,5 +1,5 @@
module Rack
module Attack
class Attack
class Allow2Ban < Fail2Ban
class << self
protected

View file

@ -1,5 +1,5 @@
module Rack
module Attack
class Attack
class Blacklist < Check
def initialize(name, block)
super

View file

@ -1,5 +1,5 @@
module Rack
module Attack
class Attack
class Cache
attr_accessor :prefix

View file

@ -1,5 +1,5 @@
module Rack
module Attack
class Attack
class Check
attr_reader :name, :block, :type
def initialize(name, block)

View file

@ -1,5 +1,5 @@
module Rack
module Attack
class Attack
class Fail2Ban
class << self
def filter(discriminator, options)

View file

@ -0,0 +1,6 @@
module Rack
class Attack
class Request < ::Rack::Request
end
end
end

View file

@ -1,7 +1,7 @@
require 'delegate'
module Rack
module Attack
class Attack
class StoreProxy
def self.build(store)
# RedisStore#increment needs different behavior, so detect that

View file

@ -1,5 +1,5 @@
module Rack
module Attack
class Attack
class Throttle
MANDATORY_OPTIONS = [:limit, :period]
attr_reader :name, :limit, :period, :block

View file

@ -1,5 +1,5 @@
module Rack
module Attack
class Attack
class Track < Check
def initialize(name, block)
super

View file

@ -1,5 +1,5 @@
module Rack
module Attack
VERSION = '3.0.0'
class Attack
VERSION = '3.1.0'
end
end

View file

@ -1,5 +1,5 @@
module Rack
module Attack
class Attack
class Whitelist < Check
def initialize(name, block)
super

View file

@ -0,0 +1,19 @@
require_relative 'spec_helper'
describe 'Rack::Attack' do
describe 'helpers' do
before do
class Rack::Attack::Request
def remote_ip
ip
end
end
Rack::Attack.whitelist('valid IP') do |req|
req.remote_ip == "127.0.0.1"
end
end
allow_ok_requests
end
end