mirror of
https://github.com/samsonjs/rack-attack.git
synced 2026-04-27 15:07:41 +00:00
Attempt to improve code legibility/clarity/semantics (#357)
* attempt to improve semantics for legibility * Attempt to improve legibility by simplifying * Make it more clear that we're calling procs/blocks here * Enable rubocop Style/BlockDelimiters cop * Prefer 'request' over 'req' abbreviation for legibility/clarity * Instances of Track named 'track' not 'tracker'
This commit is contained in:
parent
d8b88cfb84
commit
08861f8d17
9 changed files with 58 additions and 57 deletions
|
|
@ -40,6 +40,9 @@ Security:
|
||||||
Lint:
|
Lint:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
|
Style/BlockDelimiters:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
Style/BracesAroundHashParameters:
|
Style/BracesAroundHashParameters:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,40 +81,40 @@ class Rack::Attack
|
||||||
blocklists
|
blocklists
|
||||||
end
|
end
|
||||||
|
|
||||||
def safelisted?(req)
|
def safelisted?(request)
|
||||||
ip_safelists.any? { |safelist| safelist.match?(req) } ||
|
ip_safelists.any? { |safelist| safelist.matched_by?(request) } ||
|
||||||
safelists.any? { |_name, safelist| safelist.match?(req) }
|
safelists.any? { |_name, safelist| safelist.matched_by?(request) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def whitelisted?(req)
|
def whitelisted?(request)
|
||||||
warn "[DEPRECATION] 'Rack::Attack.whitelisted?' is deprecated. Please use 'safelisted?' instead."
|
warn "[DEPRECATION] 'Rack::Attack.whitelisted?' is deprecated. Please use 'safelisted?' instead."
|
||||||
safelisted?(req)
|
safelisted?(request)
|
||||||
end
|
end
|
||||||
|
|
||||||
def blocklisted?(req)
|
def blocklisted?(request)
|
||||||
ip_blocklists.any? { |blocklist| blocklist.match?(req) } ||
|
ip_blocklists.any? { |blocklist| blocklist.matched_by?(request) } ||
|
||||||
blocklists.any? { |_name, blocklist| blocklist.match?(req) }
|
blocklists.any? { |_name, blocklist| blocklist.matched_by?(request) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def blacklisted?(req)
|
def blacklisted?(request)
|
||||||
warn "[DEPRECATION] 'Rack::Attack.blacklisted?' is deprecated. Please use 'blocklisted?' instead."
|
warn "[DEPRECATION] 'Rack::Attack.blacklisted?' is deprecated. Please use 'blocklisted?' instead."
|
||||||
blocklisted?(req)
|
blocklisted?(request)
|
||||||
end
|
end
|
||||||
|
|
||||||
def throttled?(req)
|
def throttled?(request)
|
||||||
throttles.any? do |_name, throttle|
|
throttles.any? do |_name, throttle|
|
||||||
throttle[req]
|
throttle.matched_by?(request)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def tracked?(req)
|
def tracked?(request)
|
||||||
tracks.each_value do |tracker|
|
tracks.each_value do |track|
|
||||||
tracker[req]
|
track.matched_by?(request)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def instrument(req)
|
def instrument(request)
|
||||||
notifier.instrument('rack.attack', req) if notifier
|
notifier.instrument('rack.attack', request) if notifier
|
||||||
end
|
end
|
||||||
|
|
||||||
def cache
|
def cache
|
||||||
|
|
@ -167,16 +167,16 @@ class Rack::Attack
|
||||||
|
|
||||||
def call(env)
|
def call(env)
|
||||||
env['PATH_INFO'] = PathNormalizer.normalize_path(env['PATH_INFO'])
|
env['PATH_INFO'] = PathNormalizer.normalize_path(env['PATH_INFO'])
|
||||||
req = Rack::Attack::Request.new(env)
|
request = Rack::Attack::Request.new(env)
|
||||||
|
|
||||||
if safelisted?(req)
|
if safelisted?(request)
|
||||||
@app.call(env)
|
@app.call(env)
|
||||||
elsif blocklisted?(req)
|
elsif blocklisted?(request)
|
||||||
self.class.blocklisted_response.call(env)
|
self.class.blocklisted_response.call(env)
|
||||||
elsif throttled?(req)
|
elsif throttled?(request)
|
||||||
self.class.throttled_response.call(env)
|
self.class.throttled_response.call(env)
|
||||||
else
|
else
|
||||||
tracked?(req)
|
tracked?(request)
|
||||||
@app.call(env)
|
@app.call(env)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -7,17 +7,15 @@ module Rack
|
||||||
@type = options.fetch(:type, nil)
|
@type = options.fetch(:type, nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
def [](req)
|
def matched_by?(request)
|
||||||
block[req].tap { |match|
|
block.call(request).tap do |match|
|
||||||
if match
|
if match
|
||||||
req.env["rack.attack.matched"] = name
|
request.env["rack.attack.matched"] = name
|
||||||
req.env["rack.attack.match_type"] = type
|
request.env["rack.attack.match_type"] = type
|
||||||
Rack::Attack.instrument(req)
|
Rack::Attack.instrument(request)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
alias_method :match?, :[]
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,12 @@ module Rack
|
||||||
Rack::Attack.cache
|
Rack::Attack.cache
|
||||||
end
|
end
|
||||||
|
|
||||||
def [](req)
|
def matched_by?(request)
|
||||||
discriminator = block[req]
|
discriminator = block.call(request)
|
||||||
return false unless discriminator
|
return false unless discriminator
|
||||||
|
|
||||||
current_period = period.respond_to?(:call) ? period.call(req) : period
|
current_period = period.respond_to?(:call) ? period.call(request) : period
|
||||||
current_limit = limit.respond_to?(:call) ? limit.call(req) : limit
|
current_limit = limit.respond_to?(:call) ? limit.call(request) : limit
|
||||||
key = "#{name}:#{discriminator}"
|
key = "#{name}:#{discriminator}"
|
||||||
count = cache.count(key, current_period)
|
count = cache.count(key, current_period)
|
||||||
|
|
||||||
|
|
@ -32,15 +32,15 @@ module Rack
|
||||||
:period => current_period,
|
:period => current_period,
|
||||||
:limit => current_limit
|
:limit => current_limit
|
||||||
}
|
}
|
||||||
(req.env['rack.attack.throttle_data'] ||= {})[name] = data
|
(request.env['rack.attack.throttle_data'] ||= {})[name] = data
|
||||||
|
|
||||||
(count > current_limit).tap do |throttled|
|
(count > current_limit).tap do |throttled|
|
||||||
if throttled
|
if throttled
|
||||||
req.env['rack.attack.matched'] = name
|
request.env['rack.attack.matched'] = name
|
||||||
req.env['rack.attack.match_discriminator'] = discriminator
|
request.env['rack.attack.match_discriminator'] = discriminator
|
||||||
req.env['rack.attack.match_type'] = type
|
request.env['rack.attack.match_type'] = type
|
||||||
req.env['rack.attack.match_data'] = data
|
request.env['rack.attack.match_data'] = data
|
||||||
Rack::Attack.instrument(req)
|
Rack::Attack.instrument(request)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
module Rack
|
module Rack
|
||||||
class Attack
|
class Attack
|
||||||
class Track
|
class Track
|
||||||
extend Forwardable
|
|
||||||
|
|
||||||
attr_reader :filter
|
attr_reader :filter
|
||||||
|
|
||||||
def initialize(name, options = {}, block)
|
def initialize(name, options = {}, block)
|
||||||
|
|
@ -15,7 +13,9 @@ module Rack
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def_delegator :@filter, :[]
|
def matched_by?(request)
|
||||||
|
filter.matched_by?(request)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -20,24 +20,24 @@ end
|
||||||
describe 'when Redis is offline' do
|
describe 'when Redis is offline' do
|
||||||
include OfflineExamples
|
include OfflineExamples
|
||||||
|
|
||||||
before {
|
before do
|
||||||
@cache = Rack::Attack::Cache.new
|
@cache = Rack::Attack::Cache.new
|
||||||
# Use presumably unused port for Redis client
|
# Use presumably unused port for Redis client
|
||||||
@cache.store = ActiveSupport::Cache::RedisStore.new(:host => '127.0.0.1', :port => 3333)
|
@cache.store = ActiveSupport::Cache::RedisStore.new(:host => '127.0.0.1', :port => 3333)
|
||||||
}
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'when Memcached is offline' do
|
describe 'when Memcached is offline' do
|
||||||
include OfflineExamples
|
include OfflineExamples
|
||||||
|
|
||||||
before {
|
before do
|
||||||
Dalli.logger.level = Logger::FATAL
|
Dalli.logger.level = Logger::FATAL
|
||||||
|
|
||||||
@cache = Rack::Attack::Cache.new
|
@cache = Rack::Attack::Cache.new
|
||||||
@cache.store = Dalli::Client.new('127.0.0.1:22122')
|
@cache.store = Dalli::Client.new('127.0.0.1:22122')
|
||||||
}
|
end
|
||||||
|
|
||||||
after {
|
after do
|
||||||
Dalli.logger.level = Logger::INFO
|
Dalli.logger.level = Logger::INFO
|
||||||
}
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -37,13 +37,13 @@ describe Rack::Attack::Cache do
|
||||||
store = Rack::Attack::StoreProxy.build(store)
|
store = Rack::Attack::StoreProxy.build(store)
|
||||||
|
|
||||||
describe "with #{store.class}" do
|
describe "with #{store.class}" do
|
||||||
before {
|
before do
|
||||||
@cache = Rack::Attack::Cache.new
|
@cache = Rack::Attack::Cache.new
|
||||||
@key = "rack::attack:cache-test-key"
|
@key = "rack::attack:cache-test-key"
|
||||||
@expires_in = 1
|
@expires_in = 1
|
||||||
@cache.store = store
|
@cache.store = store
|
||||||
delete(@key)
|
delete(@key)
|
||||||
}
|
end
|
||||||
|
|
||||||
after { delete(@key) }
|
after { delete(@key) }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,15 +47,15 @@ describe 'Rack::Attack.track' do
|
||||||
|
|
||||||
describe "without limit and period options" do
|
describe "without limit and period options" do
|
||||||
it "should assign the track filter to a Check instance" do
|
it "should assign the track filter to a Check instance" do
|
||||||
tracker = Rack::Attack.track("homepage") { |req| req.path == "/" }
|
track = Rack::Attack.track("homepage") { |req| req.path == "/" }
|
||||||
tracker.filter.class.must_equal Rack::Attack::Check
|
track.filter.class.must_equal Rack::Attack::Check
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "with limit and period options" do
|
describe "with limit and period options" do
|
||||||
it "should assign the track filter to a Throttle instance" do
|
it "should assign the track filter to a Throttle instance" do
|
||||||
tracker = Rack::Attack.track("homepage", :limit => 10, :period => 10) { |req| req.path == "/" }
|
track = Rack::Attack.track("homepage", :limit => 10, :period => 10) { |req| req.path == "/" }
|
||||||
tracker.filter.class.must_equal Rack::Attack::Throttle
|
track.filter.class.must_equal Rack::Attack::Throttle
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -36,14 +36,14 @@ class MiniTest::Spec
|
||||||
end
|
end
|
||||||
|
|
||||||
def app
|
def app
|
||||||
Rack::Builder.new {
|
Rack::Builder.new do
|
||||||
# Use Rack::Lint to test that rack-attack is complying with the rack spec
|
# Use Rack::Lint to test that rack-attack is complying with the rack spec
|
||||||
use Rack::Lint
|
use Rack::Lint
|
||||||
use Rack::Attack
|
use Rack::Attack
|
||||||
use Rack::Lint
|
use Rack::Lint
|
||||||
|
|
||||||
run lambda { |_env| [200, {}, ['Hello World']] }
|
run lambda { |_env| [200, {}, ['Hello World']] }
|
||||||
}.to_app
|
end.to_app
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.it_allows_ok_requests
|
def self.it_allows_ok_requests
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue