Skip to content

Commit

Permalink
added error message and clear function
Browse files Browse the repository at this point in the history
  • Loading branch information
kpd committed Dec 29, 2012
1 parent a148254 commit 1d34d35
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 3 deletions.
19 changes: 19 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ sensible defaults (in *italics*).
Which HTTP field(s) to use to rate-limit. May be a string or a list. *none*
``rate``:
The number of requests per unit time allowed. *5/m*
``error_message``:
Optional error message passed to the 403 exception. This will be passed.



``from ratelimit.decorators import clear`` can be called to reset the limiting for a given ip=True/False, field combination. While it is in the decorator module, it is *not* a decorator.



Examples
Expand Down Expand Up @@ -69,6 +76,18 @@ Examples
# Allow 4 reqs/hour.
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)

# if user logged in OK:
clear(field='username')

This comment has been minimized.

Copy link
@jsocol

jsocol Jan 2, 2013

This example should be clear(request, field='username'), right?


return HttpResponse()


Acknowledgements
================
Expand Down
4 changes: 4 additions & 0 deletions ratelimit/backends/cachebe.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ def count(self, request, ip=True, field=None, period=60):
def limit(self, request, ip=True, field=None, count=5):
counters = cache.get_many(self._keys(request, ip, field))
return any((v > count) for v in counters.values())

def clear(self, request, ip=True, field=None):
cache.delete_many(self._keys(request, ip, field))

8 changes: 5 additions & 3 deletions ratelimit/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ def _split_rate(rate):


_backend = CacheBackend()
def clear(request, ip=True, field=None):
"reset counts for these parameters"
_backend.clear(request, ip, field)


def ratelimit(ip=True, block=False, method=['POST'], field=None, rate='5/m'):
def ratelimit(ip=True, block=False, method=['POST'], field=None, rate='5/m', error_message=None):
def decorator(fn):
count, period = _split_rate(rate)

Expand All @@ -47,7 +49,7 @@ def _wrapped(request, *args, **kw):
_backend.count(request, ip, field, period)
if _backend.limit(request, ip, field, count):
if block:
return HttpResponseForbidden()
return HttpResponseForbidden() if error_message is None else HttpResponseForbidden(error_message)

This comment has been minimized.

Copy link
@jsocol

jsocol Jan 2, 2013

I'm wondering if this should raise PermissionDenied instead, to let the normal 403 handler pick it up.

request.limited = True
return fn(request, *args, **kw)
return _wrapped
Expand Down

0 comments on commit 1d34d35

Please sign in to comment.