Rate Limiter

Rate Limiting is an essential aspect of security. By providing unlimited requests, it could cause strain on servers and may also lead to malicious activities as anyone can make calls to the website any number of times. We can reduce such activities to some extent by limiting the number of requests a user can make to our extension via rate_limiter module. For example, if we are writing an Ardent extension, we can implement rate limiter in our extension as follows:

from q2_sdk.core.rate_limiter import RateLimiter
import ipaddress

class FooArdentHandler(Q2ArdentRequestHandler):

    def __init__(self, application, request, **kwargs):
        super().__init__(application, request, **kwargs)
        whitelist_networks = [ipaddress.ip_network('0.0.0.0/28')]
        blacklist_networks = [ipaddress.ip_network('1.2.3.4/32')]
        self.rate_limiters = [
        RateLimiter(
            self.logger,
            5,
            5,
            3,
            self.request,
            whitelist_networks=whitelist_networks,
            blacklist_networks=blacklist_networks)
        ]

RateLimiter has the following instance variables:

  • max_tokens - Total number of attempts allowed before denial

  • refill_period - time in seconds after which token gets refilled

  • refill_amount - Number of tokens that gets added each refill period

  • request - HTTPServerRequest reference IP and other info

  • whitelist_networks - List of IPv4Networks that will be automatically allowed. i.e. ipaddress.IPv4Network(‘13.249.59.85/32’)

  • blacklist_networks - List of IPv4Networks that will be automatically denied. i.e. ipaddress.IPv4Network(‘13.249.59.85/32’)

  • whitelist_regex - (Deprecated) IP addresses that match this pattern will be automatically allowed

  • blacklist_regex - (Deprecated) IP addresses that match this pattern will be automatically denied

  • name - Will be appended to the cache key for uniqueness

  • segment_by_ip - If True, each IP address gets its own rate limiting bucket.

We can check which IP address is allowed or denied with is_allowed method. Returns True if the IP address is in the list of whitelist_networks and returns False if it is blacklist_networks. If these networks are not listed then this method calculates the remaining tokens from cache and returns False along with a warning message if there are no remaining tokens or else returns True.

The RateLimiter class also contains a decorator object allowing the setting or rate limits per function call .:

from q2_sdk.core.rate_limiter import rate_limit
import ipaddress

class FooArdentHandler(Q2ArdentRequestHandler):
    ...

    @rate_limit(max_tokens=1000)
    def submit():
        ...

    @rate_limit(
        max_tokens=5, refill_period=5, refill_amount=3,
        whitelist_networks=[ipaddress.ip_network('0.0.0.0/28')],
        blacklist_networks=[ipaddress.ip_network('1.2.3.4/32')]
    )
    def default():
        ...