Using Django Ratelimit¶
Use as a decorator¶
The @ratelimit
view decorator provides several optional arguments
with sensible defaults (in italics).
Import:
from ratelimit.decorators import ratelimit
-
@
ratelimit
(ip=True, block=False, method=None, field=None, rate='5/m', skip_if=None, keys=None)¶ Parameters: - ip –
True Whether to rate-limit based on the IP from
REMOTE_ADDR
.Note
If you’re using a reverse proxy, set this to False and use the
keys
argument. - block – False Whether to block the request instead of annotating.
- method – None Which HTTP method(s) to rate-limit. May be a string, a
list/tuple, or
None
for all methods. - field – None Which HTTP GET/POST argument field(s) to use to rate-limit. May be a string or a list of strings.
- rate –
‘5/m’ The number of requests per unit time allowed. Valid units are:
s
- secondsm
- minutesh
- hoursd
- days
- skip_if – None If specified, pass this parameter a callable
(e.g. lambda function) that takes the current request. If the
callable returns a value that evaluates to True, the rate
limiting is skipped for that particular view. This is useful
to do things like selectively deactivating rate limiting based
on a value in your settings file, or based on an attirbute in
the current request object. (Also see the
RATELIMIT_ENABLE
setting below.) - keys –
None Specify a function or list of functions that take the request object and return string keys. This allows you to define custom logic (for example, use an authenticated user ID or unauthenticated IP address).
Note
If you’re using a reverse proxy, pass in a function that pulls the appropriate field from
request.META
for the actual ip address of the client.
- ip –
Examples:
@ratelimit()
def myview(request):
# Will be true if the same IP makes more than 5 requests/minute.
was_limited = getattr(request, 'limited', False)
return HttpResponse()
@ratelimit(block=True)
def myview(request):
# If the same IP makes >5 reqs/min, will raise Ratelimited
return HttpResponse()
@ratelimit(field='username')
def login(request):
# If the same username OR IP is used >5 times/min, this will be True.
# The `username` value will come from GET or POST, determined by the
# request method.
was_limited = getattr(request, 'limited', False)
return HttpResponse()
@ratelimit(method='POST')
def login(request):
# Only apply rate-limiting to POSTs.
return HttpResponseRedirect()
@ratelimit(field=['username', 'other_field'])
def login(request):
# Use multiple field values.
return HttpResponse()
@ratelimit(rate='4/h')
def slow(request):
# Allow 4 reqs/hour.
return HttpResponse()
@ratelimit(skip_if=lambda request: getattr(request, 'some_attribute', False))
def skipif1(request):
# Conditionally skip rate limiting (example 1)
return HttpResponse()
@ratelimit(skip_if=lambda request: settings.MYAPP_DEACTIVATE_RATE_LIMITING)
def skipif2(request):
# Conditionally skip rate limiting (example 2)
return HttpResponse()
@ratelimit(keys=lambda x: 'min', rate='1/m')
@ratelimit(keys=lambda x: 'hour', rate='10/h')
@ratelimit(keys=lambda x: 'day', rate='50/d')
def post(request):
# Stack them.
# Note: once a decorator limits the request, the ones after
# won't count the request for limiting.
return HttpResponse()
@ratelimit(ip=False,
keys=lambda req: req.META.get('HTTP_X_CLUSTER_CLIENT_IP',
req.META['REMOTE_ADDR']))
def post(request):
# This will use the HTTP_X_CLUSTER_CLIENT_IP and default to
# REMOTE_ADDR if that's not set. This is how you'd set up your
# rate limiting if you're behind a reverse proxy.
#
# It's important to set ip to False here. Otherwise it'll use
# limit on EITHER HTTP_X_CLUSTER_CLIENT_IP or REMOTE_ADDR and
# the end result is that everything will be throttled.
return HttpResponse()
Helper Function¶
In some cases the decorator is not flexible enough. If this is an
issue you use the is_ratelimited
helper function. It’s similar to
the decorator.
Import:
from ratelimit.helpers import is_ratelimited
-
is_ratelimited
(request, increment=False, ip=True, method=None, field=None, rate='5/m', keys=None)¶ Parameters: - request – (Required) The request object.
- increment – False Whether to increment the count.
- ip – True Whether to rate-limit based on the IP.
- method – None Which HTTP method(s) to rate-limit. May be a string, a
list/tuple, or
None
for all methods. - field – None Which HTTP field(s) to use to rate-limit. May be a string or a list.
- rate – ‘5/m’ The number of requests per unit time allowed.
- keys – None Specify a function or list of functions that take the request object and return string keys. This allows you to define custom logic (for example, use an authenticated user ID or unauthenticated IP address).
Exceptions¶
-
class
ratelimit.exceptions.
Ratelimited
¶ If a request is ratelimited and
block
is set toTrue
, Ratelimit will raiseratelimit.exceptions.Ratelimited
.This is a subclass of Django’s
PermissionDenied
exception, so if you don’t need any special handling beyond the built-in 403 processing, you don’t have to do anything.
Middleware¶
There is optional middleware to use a custom view to handle Ratelimited
exceptions.
To use it, add ratelimit.middleware.RatelimitMiddleware
to your
MIDDLEWARE_CLASSES
(toward the bottom of the list) and set
RATELIMIT_VIEW
to the full path of a view you want to use.
The view specified in RATELIMIT_VIEW
will get two arguments, the
request
object (after ratelimit processing) and the exception.