diff --git a/lib/rack/attack/cache.rb b/lib/rack/attack/cache.rb index ecbd3368..9111ab8a 100644 --- a/lib/rack/attack/cache.rb +++ b/lib/rack/attack/cache.rb @@ -55,7 +55,7 @@ def delete(unprefixed_key) def reset! if store.respond_to?(:delete_matched) - store.delete_matched("#{prefix}*") + store.delete_matched(/#{prefix}*/) else raise( Rack::Attack::IncompatibleStoreError, diff --git a/lib/rack/attack/store_proxy/redis_proxy.rb b/lib/rack/attack/store_proxy/redis_proxy.rb index 830d39de..599213ae 100644 --- a/lib/rack/attack/store_proxy/redis_proxy.rb +++ b/lib/rack/attack/store_proxy/redis_proxy.rb @@ -45,11 +45,12 @@ def delete(key, _options = {}) def delete_matched(matcher, _options = nil) cursor = "0" + source = matcher.source rescuing do # Fetch keys in batches using SCAN to avoid blocking the Redis server. loop do - cursor, keys = scan(cursor, match: matcher, count: 1000) + cursor, keys = scan(cursor, match: source, count: 1000) del(*keys) unless keys.empty? break if cursor == "0" end diff --git a/spec/rack_attack_spec.rb b/spec/rack_attack_spec.rb index 40936017..54f2f1df 100644 --- a/spec/rack_attack_spec.rb +++ b/spec/rack_attack_spec.rb @@ -124,5 +124,31 @@ _(redis.get("#{Rack::Attack.cache.prefix}::key")).must_be_nil end end + + if defined?(Redis) && defined?(ActiveSupport::Cache::RedisCacheStore) + it 'should delete rack attack keys' do + redis_cache_store = ActiveSupport::Cache::RedisCacheStore.new(namespace: 'ns') + redis_cache_store.write('key', 'value') + redis_cache_store.write("#{Rack::Attack.cache.prefix}::key", 'value') + Rack::Attack.cache.store = redis_cache_store + Rack::Attack.reset! + + _(redis_cache_store.read('key')).must_equal 'value' + _(redis_cache_store.read("#{Rack::Attack.cache.prefix}::key")).must_be_nil + end + end + + if defined?(ActiveSupport::Cache::MemoryStore) + it 'should delete rack attack keys' do + memory_store = ActiveSupport::Cache::MemoryStore.new(namespace: 'ns') + memory_store.write('key', 'value') + memory_store.write("#{Rack::Attack.cache.prefix}::key", 'value') + Rack::Attack.cache.store = memory_store + Rack::Attack.reset! + + _(memory_store.read('key')).must_equal 'value' + _(memory_store.read("#{Rack::Attack.cache.prefix}::key")).must_be_nil + end + end end end