Package: falcon-limiter
Falcon-LimiterThis library provides advanced rate limiting support for theFalcon web framework.Rate limiting is provided with the help of the popularLimitslibrary.This library aims to be compatible with CPython 3.6+ and PyPy 3.5+.DocumentationYou can find the documentation of this library onRead the Docs.QuickstartWSGIQuick example - usingfixed-windowstrategy and storing the hits against limits in the memory:import falcon
from falcon_limiter import Limiter
from falcon_limiter.utils import get_remote_addr

limiter = Limiter(
    key_func=get_remote_addr,
    default_limits="5 per minute,2 per second"
)

# use the default limit for all methods of this class
@limiter.limit()
class ThingsResource:
    def on_get(self, req, resp):
        resp.body = 'Hello world!'

# add the limiter middleware to the Falcon app
app = falcon.API(middleware=limiter.middleware)

things = ThingsResource()
app.add_route('/things', things)ASGI (Async)Quick example - usingfixed-windowstrategy and storing the hits against limits in the memory:import falcon.asgi
from falcon_limiter import AsyncLimiter
from falcon_limiter.utils import get_remote_addr

limiter = AsyncLimiter(
    key_func=get_remote_addr,
    default_limits="5 per minute,2 per second"
)

# use the default limit for all methods of this class
@limiter.limit()
class ThingsResource:
    async def on_get(self, req, resp):
        resp.body = 'Hello world!'

# add the limiter middleware to the Falcon app
app = falcon.asgi.App(middleware=limiter.middleware)

things = ThingsResource()
app.add_route('/things', things)See documentation for more about Async.A more complicated exampleWhen making calls against this app, above >5 calls per minute or >2 per seconds you will receive
an HTTP 429 error response with message:"Reached allowed limit 5 hits per 1 minute!"A second, more complicated example - using themoving-windowstrategy with a shared Redis backend
and running the application behind a reverse proxy behind a reverse proxy:import falcon
from falcon_limiter import Limiter

# a custom key function
def get_access_route_addr(req, resp, resource, params) -> str:
    """ Get the requestor's IP by discounting 1 reverse proxy
    """
    return req.access_route[-2]

limiter = Limiter(
    key_func=get_access_route_addr,
    default_limits="5 per minute,2 per second",
    # only count HTTP 200 responses against the limit:
    default_deduct_when=lambda req, resp, resource, req_succeeded:
        resp.status == falcon.HTTP_200,
    config={
        'RATELIMIT_KEY_PREFIX': 'myapp',  # to allow multiple apps in the same Redis db
        'RATELIMIT_STORAGE_URL': f'redis://:{REDIS_PSW}@{REDIS_HOST}:{REDIS_PORT}',
        'RATELIMIT_STRATEGY': 'moving-window'
    }
)

class ThingsResource:
    # no rate limit on this method
    def on_get(self, req, resp):
        resp.body = 'Hello world!'

    # a more strict rate limit applied to this method
    # with a custom key function serving up the user_id
    # from the request context as key
    @limiter.limit(limits="3 per minute,1 per second",
        key_func=lambda req, resp, resource, params: req.context.user_id)
    def on_post(self, req, resp):
        resp.body = 'Hello world!'

class SpecialResource:
    # dynamic_limits allowing the 'admin' user a higher limit than others
    @limiter.limit(dynamic_limits=lambda req, resp, resource, params:
        '999/minute,9999/second' if req.context.user == 'admin'
        else '5 per minute,2/second')
    def on_get(self, req, resp):
        resp.body = 'Hello world!'

# add the limiter middleware to the Falcon app
app = falcon.API(middleware=limiter.middleware)

things = ThingsResource()
special = SpecialResource()
app.add_route('/things', things)
app.add_route('/special', special)For more details please read the documentation atRead the DocsDevelopmentFor the development environment we usePipenvand for packaging we useFlit.DocumentationThe documentation is built via Sphinx following theGoogle docstring styleand hosted onRead the Docs.To review the documentation locally before committing:$ make docs
$ cd docs
$ python -m http.server 8088Now you can access the documentation locally underhttp://127.0.0.1:8088/_build/html/Development environmentYou will need Python 3.6-3.9 and PyPy3 and its source package installed to runtoxin all environments.We do use type hinting and run MyPy on those, but unfortunately MyPy currently breaks
the PyPy tests due to thetyped-astpackage's "bug" (seehttps://github.com/python/typed_ast/issues/97). Also with Pipenv you can't
have a second Pipfile. This is why for now we don't havemypylisted as a dev package
in the Pipfile.CreditsOur library uses the popularLimitslibrary
for most of the backend operations.