Rate Limit¶
Keywords: rate limiter, prevent brute force, client limit, rate limit key, request throttling, slide window, redis rate limit
Protect your application from brute-force attacks and abuse with Asok’s built-in rate limiter.
Quick Start (Decorator)¶
The easiest way to protect a specific page is using the @rate_limit decorator in your page.py:
# src/pages/protected/page.py
from asok import rate_limit
@rate_limit("5/m") # Limit to 5 requests per minute
def render(request):
return "This page is protected!"
Limit Syntax¶
Asok supports human-readable strings for defining limits:
"10/s": 10 requests per second"60/m": 60 requests per minute"1000/h": 1000 requests per hour"5000/d": 5000 requests per day
Global Middleware¶
To apply a global rate limit, create src/middlewares/ratelimit.py:
from asok import RateLimit
# Use a string limit for simplicity
limiter = RateLimit("100/m")
def handle(request, next):
return limiter(request, next)
Programmatic Rate Limiting (Custom Responses)¶
If you want to perform custom actions (like flashing an error message) instead of rendering the default 429 page when a limit is exceeded, you can check the rate limit programmatically inside your view function.
To do this, call request.rate_limit() inside a try/except block and catch RateLimitExceeded:
from asok import Request, RateLimitExceeded
from asok.forms import Form
from my_app.models import Contact
def post(request: Request):
form = Form.from_model(Contact, request)
try:
# Check limit programmatically
request.rate_limit("3/day")
if form.validate():
Contact.create(**form.data)
return request.block("page.html", "main", form=form.reset())
except RateLimitExceeded:
# Catch and handle it, e.g. using a flash message
request.flash("error", "You have exceeded the rate limit. Please try again later.")
return request.html('page.html', form=form)
[!NOTE]
When using
request.rate_limit()without aprefix, Asok automatically generates a unique prefix based on the calling module and function name (e.g.rl:src.pages.contact.post).If
RateLimitExceededis raised but not caught inside the view, it bubbles up and automatically triggers the framework’s default 429 error page rendering.
5. Options¶
Option |
Type |
Description |
|---|---|---|
|
|
Maximum requests (e.g., |
|
|
Window duration in seconds (if |
|
|
Custom function to identify clients (default: IP address). |
|
|
Optional |
|
|
Optional custom prefix for the rate-limit cache keys (defaults to |