Adding A Rate Limiter Middleware To A Robyn Server | Python

Photo by Sam Xu on Unsplash

Adding A Rate Limiter Middleware To A Robyn Server | Python

In this article, we are going to learn how to add a rate limiter middleware to a Robyn server through robyn-rate-limits, a plugin developed by IdoKendo.

Requirements

  • Python 3 installed

  • Pip installed

Rate Limiter

According to this article, published by CloudFlare, a rate limiter is a strategy for limiting network traffic. It puts a cap on how often someone can repeat an action within a certain timeframe – for instance, trying to log in to an account. Rate limiting can help stop certain kinds of malicious bot activity. It can also reduce strain on web servers.

Rate limiting is often employed to stop bad bots from negatively impacting a website or application. Bot attacks that rate limiting can help mitigate include Brute force attacks, DoS and DDoS attacks and Web scraping.

Rate limiting also protects against API overuse, which is not necessarily malicious or due to bot activity, but is important to prevent nonetheless.

Robyn Rate Limiter Plugin

According to the documentation, the rate limiter plugin enables you to implement rate limiting for your Robyn application's routes. It helps prevent abuse, and brute-force attacks and ensures fair usage of your resources.

To use this plugin, we have to install it first:

 pip install robyn robyn-rate-limits

We create a python file, app.py to create a Robyn server.

app.py

from robyn import Robyn, Robyn
from robyn_rate_limits import InMemoryStore
from robyn_rate_limits import RateLimiter

app = Robyn(__file__)
limiter = RateLimiter(store=InMemoryStore, calls_limit=3, limit_ttl=100)

@app.before_request()
def middleware(request: Request):
    return limiter.handle_request(app, request)


@app.get("/")
def h():
    return "Hello, World!"

app.start(port=8080)

In the example above (taken from the documentation), the robyn-rate-limits plugin is used to enforce a rate limit of 3 requests per 100-seconds window for specific routes. If a client exceeds this limit, they will receive a "Too many requests" message.

We start our server as usually do, by running py app.py command in our console.

Now, we have to create a python script, to test the rate limiter.

test_limiter.py

For this script we have to import the requests library.

import requests
import time

def test_rate_limiter(url, rate_limit, time_window):
    """Tests a rate limiter with the given parameters."""

    start_time = time.time()
    allowed_requests = 0
    blocked_requests = 0

    while time.time() - start_time < time_window:
        try:
            response = requests.get(url)
            response.raise_for_status()  # Raise an exception for non-200 status codes
            allowed_requests += 1
        except requests.exceptions.RequestException as e:
            blocked_requests += 1
            print(f"Request blocked: {e}")

        time.sleep(time_window / rate_limit)  # Delay to respect the rate limit

    print(f"Allowed requests: {allowed_requests}")
    print(f"Blocked requests: {blocked_requests}")

# Example usage:
url = "http://localhost:8080/"  # Replace with the actual URL
rate_limit = 3  # Requests per second
time_window = 5  # Seconds

test_rate_limiter(url, rate_limit, time_window)

In the example above, we define the test_rate_limiter() function with three parameters: url, rate_limit and time_window.

This program makes requests to an URL and tracks allowed and blocked requests. response.raise_for_status() is if the status code in the response is different from a successful status code(200), it will raise an exception. And it will print the exception, in our case, it should be a "Too many request" message. time.sleep pauses execution to respect the rate limit.

We set the url to the URL address where our Robyn server is receiving requests, rate_limit to 3, and the time_window to 5.

We run this program, executing this command in another terminal: py test_limiter.py.

Now, we should receive the following response in our console:

Conclusion

This is an easy to use and an useful plugin that allow us to build more resilient services with Robyn. Also, this plugin has a feature that uses Redis to store the calls, you can take a look to the plugin's repository for an example of how to use it.

Thank you for taking the time to read this article.

If you have any recommendations about other packages, architectures, how to improve my code, my English, or anything; please leave a comment or contact me through Twitter, or LinkedIn.

Resources

robyn-rate-limits repository

robyn-rate-limits documentation

What is rate limiting

What Is a Rate Limiter?