Support ActiveSupport::RedisCacheStore

This commit is contained in:
Brian Kephart 2018-05-13 18:18:50 -05:00 committed by Gonzalo Rodriguez
parent d831f2490e
commit 4cc8d7d854
No known key found for this signature in database
GPG key ID: 5DB8B81B049B8AB1
5 changed files with 51 additions and 15 deletions

View file

@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
- Adds support for ActiveSupport::RedisCacheStore
## [5.2.0] - 2018-03-29
### Added

View file

@ -8,18 +8,19 @@ class Rack::Attack
class MisconfiguredStoreError < StandardError; end
class MissingStoreError < StandardError; end
autoload :Cache, 'rack/attack/cache'
autoload :Check, 'rack/attack/check'
autoload :Throttle, 'rack/attack/throttle'
autoload :Safelist, 'rack/attack/safelist'
autoload :Blocklist, 'rack/attack/blocklist'
autoload :Track, 'rack/attack/track'
autoload :StoreProxy, 'rack/attack/store_proxy'
autoload :DalliProxy, 'rack/attack/store_proxy/dalli_proxy'
autoload :MemCacheProxy, 'rack/attack/store_proxy/mem_cache_proxy'
autoload :RedisStoreProxy, 'rack/attack/store_proxy/redis_store_proxy'
autoload :Fail2Ban, 'rack/attack/fail2ban'
autoload :Allow2Ban, 'rack/attack/allow2ban'
autoload :Cache, 'rack/attack/cache'
autoload :Check, 'rack/attack/check'
autoload :Throttle, 'rack/attack/throttle'
autoload :Safelist, 'rack/attack/safelist'
autoload :Blocklist, 'rack/attack/blocklist'
autoload :Track, 'rack/attack/track'
autoload :StoreProxy, 'rack/attack/store_proxy'
autoload :DalliProxy, 'rack/attack/store_proxy/dalli_proxy'
autoload :MemCacheProxy, 'rack/attack/store_proxy/mem_cache_proxy'
autoload :RedisStoreProxy, 'rack/attack/store_proxy/redis_store_proxy'
autoload :RedisCacheStoreProxy, 'rack/attack/store_proxy/redis_cache_store_proxy'
autoload :Fail2Ban, 'rack/attack/fail2ban'
autoload :Allow2Ban, 'rack/attack/allow2ban'
class << self
attr_accessor :notifier, :blocklisted_response, :throttled_response

View file

@ -1,9 +1,9 @@
module Rack
class Attack
module StoreProxy
PROXIES = [DalliProxy, MemCacheProxy, RedisStoreProxy].freeze
PROXIES = [DalliProxy, MemCacheProxy, RedisStoreProxy, RedisCacheStoreProxy].freeze
ACTIVE_SUPPORT_WRAPPER_CLASSES = Set.new(['ActiveSupport::Cache::MemCacheStore', 'ActiveSupport::Cache::RedisStore']).freeze
ACTIVE_SUPPORT_WRAPPER_CLASSES = Set.new(['ActiveSupport::Cache::MemCacheStore', 'ActiveSupport::Cache::RedisStore', 'ActiveSupport::Cache::RedisCacheStore']).freeze
ACTIVE_SUPPORT_CLIENTS = Set.new(['Redis::Store', 'Dalli::Client', 'MemCache']).freeze
def self.build(store)

View file

@ -0,0 +1,30 @@
require 'delegate'
module Rack
class Attack
module StoreProxy
class RedisCacheStoreProxy < SimpleDelegator
def self.handle?(store)
defined?(::ActiveSupport::Cache::RedisCacheStore) && store.is_a?(::ActiveSupport::Cache::RedisCacheStore)
end
def increment(name, amount, options = {})
# Redis doesn't check expiration on the INCRBY command. See https://redis.io/commands/expire
count = redis.pipelined do
redis.incrby(name, amount)
redis.expire(name, options[:expires_in]) if options[:expires_in]
end
count.first
end
def read(name, options = {})
super(name, options.merge!({ raw: true }))
end
def write(name, value, options = {})
super(name, value, options.merge!({ raw: true }))
end
end
end
end
end

View file

@ -2,7 +2,7 @@ require_relative '../spec_helper'
describe Rack::Attack::Cache do
# A convenience method for deleting a key from cache.
# Slightly differnet than @cache.delete, which adds a prefix.
# Slightly different than @cache.delete, which adds a prefix.
def delete(key)
if @cache.store.respond_to?(:delete)
@cache.store.delete(key)
@ -18,6 +18,7 @@ describe Rack::Attack::Cache do
require 'active_support/cache/dalli_store'
require 'active_support/cache/mem_cache_store'
require 'active_support/cache/redis_store'
require 'active_support/cache/redis_cache_store' if ActiveSupport.version.to_s.to_f >= 5.2
require 'connection_pool'
cache_stores = [
@ -30,6 +31,8 @@ describe Rack::Attack::Cache do
Redis::Store.new
]
cache_stores << ActiveSupport::Cache::RedisCacheStore.new if defined?(ActiveSupport::Cache::RedisCacheStore)
cache_stores.each do |store|
store = Rack::Attack::StoreProxy.build(store)