From dd6c09e58111fc30b67f8ddff131133c0753540a Mon Sep 17 00:00:00 2001 From: Cristian Greco Date: Sun, 7 Jul 2019 22:10:17 +0100 Subject: [PATCH] Failsafe on Redis error replies in RedisCacheStoreProxy. RedisCacheStoreProxy will blow up when RedisCacheStore raises a CommandError exception. In fact, by default the proxied store only handles BaseConnectionError exceptions, but will let bubble up any other type of exception from the underlying client. This pull request uses the same approach from RedisProxy, where store operations are wrapped in a `rescuing` block that rescues and ignores BaseError exceptions (the most generic exception class that can be raised by the Redis client). --- .../store_proxy/redis_cache_store_proxy.rb | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/lib/rack/attack/store_proxy/redis_cache_store_proxy.rb b/lib/rack/attack/store_proxy/redis_cache_store_proxy.rb index 78807f8..f4081be 100644 --- a/lib/rack/attack/store_proxy/redis_cache_store_proxy.rb +++ b/lib/rack/attack/store_proxy/redis_cache_store_proxy.rb @@ -15,17 +15,33 @@ module Rack # # So in order to workaround this we use RedisCacheStore#write (which sets expiration) to initialize # the counter. After that we continue using the original RedisCacheStore#increment. - if options[:expires_in] && !read(name) - write(name, amount, options) + rescuing do + if options[:expires_in] && !read(name) + write(name, amount, options) - amount - else - super + amount + else + super + end end end + def read(*_args) + rescuing { super } + end + def write(name, value, options = {}) - super(name, value, options.merge!(raw: true)) + rescuing do + super(name, value, options.merge!(raw: true)) + end + end + + private + + def rescuing + yield + rescue Redis::BaseError + nil end end end