Rate-limiting for django
Project description
django-ratelimiter
Rate limiting for django using limits.
Documentation: https://andriykohut.github.io/django-ratelimiter/
Installation
pip install django-ratelimiter
Usage
By default django-ratelimiter
will use the default cache.
Django configuration
To use a non-default cache define DJANGO_RATELIMITER_CACHE
in settings.py
.
# Set up django caches
CACHES = {
"custom-cache": {
"BACKEND": "django.core.cache.backends.redis.RedisCache",
"LOCATION": "redis://127.0.0.1:6379",
}
}
# "default" cache is used if setting is not defined.
DJANGO_RATELIMITER_CACHE = "custom-cache"
Any storage backend provided by limits
package can also be used by defining DJANGO_RATELIMITER_STORAGE
:
from limits.storage import RedisStorage
DJANGO_RATELIMITER_STORAGE = RedisStorage(uri="redis://localhost:6379/0")
For more details on storages refer to limits documentation.
Rate limiting strategies
- Fixed window
- Fixed Window with Elastic Expiry
- Moving Window - Only supported with
limits
storage by settingDJANGO_RATELIMITER_STORAGE
View decorator
By default all requests are rate limited
from django_ratelimiter import ratelimit
@ratelimit("5/minute")
def view(request: HttpRequest) -> HttpResponse:
return HttpResponse("OK")
Pick a rate limiting strategy, default is fixed-window
:
# options: fixed-window, fixed-window-elastic-expiry, moving-window
@ratelimit("5/minute", strategy="fixed-window-elastic-expiry")
def view(request: HttpRequest) -> HttpResponse:
return HttpResponse("OK")
You can define per-user limits using request attribute key.
@ratelimit("5/minute", key="user")
def view(request: HttpRequest) -> HttpResponse:
return HttpResponse("OK")
Callable key can be used to define more complex rules:
@ratelimit("5/minute", key=lambda r: r.user.username)
def view(request: HttpRequest) -> HttpResponse:
return HttpResponse("OK")
Rate-limit only certain methods:
@ratelimit("5/minute", methods=["POST", "PUT"])
def view(request):
return HttpResponse("OK")
Provide a custom response:
from django.http import HttpResponse
@ratelimit("5/minute", response=HttpResponse("Too many requests", status=400))
def view(request):
return HttpResponse("OK")
Using non-default storage:
from limits.storage import RedisStorage
@ratelimit("5/minute", storage=RedisStorage(uri="redis://localhost:6379/0"))
def view(request):
return HttpResponse("OK")
Middleware
Middleware can be used instead of decorators for more general cases.
from typing import Optional
from django.http import HttpRequest
from django_ratelimiter.middleware import AbstractRateLimiterMiddleware
class RateLimiterMiddleware(AbstractRateLimiterMiddleware):
def rate_for(self, request: HttpRequest) -> Optional[str]:
# allow only 100 POST requests per minute
if request.method == "POST":
return "100/minute"
# allow only 200 PUT requests per minute
if request.methid == "PUT":
return "200/minute"
# all other requests are not rate limited
return None
Middleware is customizable by overriding methods, see api reference for more details.
DRF/ninja/class-based views
django-ratelimiter
is framework-agnostic, it should work with DRF/ninja out of the box.
Class-based views are also supported with method_decorator.
See examples in test_app.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for django_ratelimiter-0.2.1-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 13dbed67844a88aa7f4ca43bd956aa5dbf4bf24b066170ca2a2064c6d9426bcb |
|
MD5 | 20ad632d97ac52e8131bdbe48a5b5fa6 |
|
BLAKE2b-256 | 85122d17821d84528f96f59c01ac4e366f597cf3bd8976280af900e9c79af5a9 |