I believe I have the same problem as described here: Flask-Limiter does not work with Flask-Restful API-based application. But I still can't get it to work. Here's my problem:
I have an
app.py
where I import all my REST-API endpoints. I use flask-RESTful resources as described in this guide: https://flask-restful.readthedocs.io/en/latest/quickstart.htmlI use the "Flask-Limiter" library for rate limiting: https://flask-limiter.readthedocs.io/en/stable/. The rate-limiter gets instantiated in a separate file, not inside
app.py
because this would create circular references betweenapp.py
and the REST-API endpoints. I think this could be the cause of my problem.
This is the rate-limiter file (located in: /controller/helpers/rate_limiter.py
)
from flask import current_app
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
limiter = Limiter(
current_app,
key_func=get_remote_address
)
This is the app.py
file (located in: /
):
from flask import Flask
from flask_restful import Api
from controller.actions.my_endpoint import MyEndpoint
flask_app = Flask(__name__)
api = Api(flask_app)
api.add_resource(MyEndpoint, '/endpoint')
flask_app.run(debug=True, use_reloader=True, host='0.0.0.0', port=8000)
And finally this is an example of an endpoint (located in: /controller/actions/my_endpoint
):
from flask_restful import reqparse, Resource
from controller.helpers.rate_limiter import limiter
class MyEndpoint(Resource):
decorators = [limiter.limit("1/minute", methods=["POST"])]
def __init__(self):
self.parser = reqparse.RequestParser()
self.parser.add_argument(
"someData", type=int, nullable=False, required=True)
def post(self):
data = self.parser.parse_args(strict=True)
someData = data.someData
return "Got your message {0}".format(someData), 200
I would expect that after the first request I would get response 429 because the rate limit of 1/minute is reached but it doesn't do that.
However, when I instantiate the limiter inside app.py
and set a default rate-limit, it works (getting that error 429):
from flask import Flask
from flask_restful import Api
from controller.db_actions.my_endpoint import MyEndpoint
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
flask_app = Flask(__name__)
limiter = Limiter(
flask_app,
key_func=get_remote_address,
default_limits=["1 per minute"]
)
api = Api(flask_app)
api.add_resource(MyEndpoint, '/endpoint')
flask_app.run(debug=True, use_reloader=True, host='0.0.0.0', port=8000)
Question: I think I'm doing something wrong with instantiating the limiter. What is it? :)