Option swallow_errors don't work with limit configured with a deduct_when option and a storage backend down
tlauga opened this issue · comments
Context:
I created a limiter with options swallow_errors=True
and in_memory_fallback_enabled=False
in case the backend storage is down so that clients still can access routes without rate-limit.
I then create a "global" limit to set a same limit on multiple routes, and I set the option deduct_when to avoid blocking user if they receive status_code != 200
test_code:
from flask import Flask
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
from flask import request
app = Flask(__name__)
my_limit = Limiter(
key_func= get_remote_address,
default_limits=["20 per day", "5 per hour"],
storage_uri="redis://localhost:6379",
storage_options={},
swallow_errors=True,
in_memory_fallback_enabled=False
)
my_limit.init_app(app)
global_limit = my_limit.shared_limit("5 per hour", scope="_global", deduct_when=lambda response: response.status_code == 200)
@app.route('/')
@global_limit
def index():
return "<p>Coucou</p>"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5001)
Expected:
If the redis backend is not up, I want my client to access route '/' without limitation.
Output:
When a client access the road '/' with redis down, an exception 111 is raised without being swallow.
Quick fix:
In extension.py file, in the __check_conditional_deductions function, I implement this try-except to avoid this problem:
def __check_conditional_deductions(self, response: flask.wrappers.Response) -> None:
for lim, args in self.context.conditional_deductions.items():
if lim.deduct_when and lim.deduct_when(response):
try:
self.limiter.hit(lim.limit, *args, cost=lim.cost)
except Exception as err:
if self._swallow_errors:
self.logger.exception(
"Failed to deduct rate limit. " "Swallowing error"
)
else:
raise err
Thanks for providing the fix. I'll try to get a 2.7.0
release out by EOD.
The fix is now available in 2.7.0