Skip to content

Latest commit

 

History

History
177 lines (121 loc) · 4.62 KB

README.rst

File metadata and controls

177 lines (121 loc) · 4.62 KB

Quart-Rate-Limiter

Build Status pypi python license

Quart-Rate-Limiter is an extension for Quart to allow for rate limits to be defined and enforced on a per route basis. The 429 error response includes a RFC7231 compliant Retry-After header and the successful responses contain headers compliant with the RateLimit Header Fields for HTTP RFC draft.

Usage

To add a rate limit first initialise the RateLimiting extension with the application,

app = Quart(__name__)
rate_limiter = RateLimiter(app)

or via the factory pattern,

rate_limiter = RateLimiter()

def create_app():
    app = Quart(__name__)
    rate_limiter.init_app(app)
    return app

Now this is done you can apply rate limits to any route by using the rate_limit decorator,

@app.route('/')
@rate_limit(1, timedelta(seconds=10))
async def handler():
    ...

Or to apply rate limits to all routes within a blueprint by using the limit_blueprint function,

blueprint = Blueprint("name", __name__)
limit_blueprint(blueprint, 1, timedelta(seconds=10))

Or to apply rate limits to all routes in an app, define the default limits when initialising the RateLimiter,

rate_limiter = RateLimiter(
    default_limits=[RateLimit(1, timedelta(seconds=10))]
)

and then to exempt a route,

@app.route("/exempt")
@rate_exempt
async def handler():
    ...

To alter the identification of remote users you can either supply a global key function when initialising the extension, or on a per route basis.

By default rate limiting information (TATs) will be stored in memory, which will result in unexpected behaviour if multiple workers are used. To solve this a redis store can be used by installing the redis extra (pip install quart-rate-limiter[redis]) and then using as so,

from quart_rate_limiter.redis_store import RedisStore

redis_store = RedisStore(address)
RateLimiter(app, store=redis_store)

This store uses redis, and any extra keyword arguments passed to the RedisStore constructor will be passed to the redis create_redis function.

A custom store is possible, see the RateLimiterStoreABC for the required interface.

Simple examples

To limit a route to 1 request per second and a maximum of 20 per minute,

@app.route('/')
@rate_limit(1, timedelta(seconds=1))
@rate_limit(20, timedelta(minutes=1))
async def handler():
    ...

Alternatively the limits argument can be used for multiple limits,

@app.route('/')
@rate_limit(
    limits=[
        RateLimit(1, timedelta(seconds=1)),
        RateLimit(20, timedelta(minutes=1)),
    ],
)
async def handler():
    ...

To identify remote users based on their authentication ID, rather than their IP,

async def key_function():
    return current_user.id

RateLimiter(app, key_function=key_function)

The key_function is a coroutine function to allow session lookups if appropriate.

Contributing

Quart-Rate-Limiter is developed on GitHub. You are very welcome to open issues or propose merge requests.

Testing

The best way to test Quart-Rate-Limiter is with Tox,

$ pip install tox
$ tox

this will check the code style and run the tests.

Help

This README is the best place to start, after that try opening an issue.