Bootstrap FreeKB - Flask - Limit Requests using flask_limiter
Flask - Limit Requests using flask_limiter

Updated:   |  Flask articles

One day, I was sitting on the couch, watching the baseball game, when out of nowhere, I got like alerts. Some hacker was attempting to break through my /basicauth route by submitted thousands of requests with common username and password combinations. Oh no. This is what sparked me to figure out how to limit requests to a route, perhaps only 1 per second from the same IP address. Enter Flask-Limiter!

We will need to update our Flask app have the flask-limiter package. For example, if running Flask in a UI such as VSCode, the pip install command can be used.

pip install flask-limiter

 

Or, if running Flask in a Docker container, you can create a Docker image from a Dockerfile that has the flask-limiter package and then use the docker build command to create the Docker image.

FROM tiangolo/uwsgi-nginx-flask:latest
RUN apt-get update -y
RUN pip install --upgrade pip
RUN pip install flask-limiter

 

Let's update main.py to include the Limiter stuff.

from flask import Flask
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address

app = Flask(__name__)

limiter = Limiter(
    get_remote_address,
    app=app,
    default_limits=["200 per day", "50 per hour"],
    storage_uri="memory://",
)

@app.route("/foo")
def foo():
    return "Hello"

@app.route("/bar")
@limiter.limit("1 per minute")
def bar():
    return "World"

if __name__ == "__main__":
    app.run()

 

There is no limit on the /foo route, so the /foo route should always return Hello. However, there is a "1 per minute" limit on the /bar route, so if you hit the /bar route twice, the second request should return something like this.

 

Almost always, Flask apps are not a single main.py file, and instead are comprised of multiple different files. Let's say your Flask app has a structure like this.

├── main.py
├── my-project (directory)
│   ├── __init__.py
│   ├── views.py

 

main.py could have the following.

from my-project import app

app = app()

if __name__ == '__main__':
    app.run()

 

And __init__.py could have this.

from flask import Flask
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address

limiter = Limiter(
    get_remote_address,
    default_limits=["1000000 per day"],
    storage_uri="memory://",
)

def app():
    app = Flask(__name__)

    from .views import views
    app.register_blueprint(views, url_prefix='/')

    limiter.init_app(app)

    return app

 

And views.py could have this.

from flask import Blueprint
from . import limiter

views = Blueprint('views', __name__)

@views.route("/foo")
def foo():
    return "Hello"

@views.route("/bar")
@limiter.limit("1 per minute")
def bar():
    return "World"

 




Did you find this article helpful?

If so, consider buying me a coffee over at Buy Me A Coffee



Comments


Add a Comment


Please enter 9ecc38 in the box below so that we can be sure you are a human.