refactor unwieldy Rack::Attack::StoreProxy.build method

This commit is contained in:
Vincent Boisard 2016-01-07 21:16:35 +01:00
parent ba9f2c3be6
commit 8d124d868e

View file

@ -2,25 +2,30 @@ module Rack
class Attack class Attack
module StoreProxy module StoreProxy
PROXIES = [DalliProxy, MemCacheProxy, RedisStoreProxy] PROXIES = [DalliProxy, MemCacheProxy, RedisStoreProxy]
USE_BASE_CLIENT = ['Redis::Store', 'Dalli::Client', 'MemCache']
def self.build(store) def self.build(store)
# RedisStore#increment needs different behavior, so detect that # RedisStore#increment needs different behavior, so detect that
# (method has an arity of 2; must call #expire separately # (method has an arity of 2; must call #expire separately
if (defined?(::ActiveSupport::Cache::RedisStore) && store.is_a?(::ActiveSupport::Cache::RedisStore)) || client = fetch_client(store)
(defined?(::ActiveSupport::Cache::MemCacheStore) && store.is_a?(::ActiveSupport::Cache::MemCacheStore)) klass = PROXIES.find { |proxy| proxy.handle?(client) }
klass ? klass.new(client) : client
end
# ActiveSupport::Cache::RedisStore doesn't expose any way to set an expiry, def self.fetch_client(store)
# so use the raw Redis::Store instead. client = store.instance_variable_get(:@data)
# We also want to use the underlying Dalli client instead of ::ActiveSupport::Cache::MemCacheStore, # RedisStore#increment needs different behavior, so detect that
# and the MemCache client if using Rails 3.x # (method has an arity of 2; must call #expire separately
client = store.instance_variable_get(:@data) #
if (defined?(::Redis::Store) && client.is_a?(Redis::Store)) || # ActiveSupport::Cache::RedisStore doesn't expose any way to set an expiry,
(defined?(Dalli::Client) && client.is_a?(Dalli::Client)) || (defined?(MemCache) && client.is_a?(MemCache)) # so use the raw Redis::Store instead.
store = store.instance_variable_get(:@data) #
end # We also want to use the underlying Dalli client instead of ::ActiveSupport::Cache::MemCacheStore,
# and the MemCache client if using Rails 3.x
USE_BASE_CLIENT.each do |klass|
return client if !client.nil? && Object.const_defined?(klass) && client.is_a?(Object.const_get(klass))
end end
klass = PROXIES.find { |proxy| proxy.handle?(store) } return store
klass ? klass.new(store) : store
end end
end end