alisaifee / flask-limiter

Rate Limiting extension for Flask

Home Page:https://flask-limiter.readthedocs.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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