Permalink
Browse files

Merge branch 'master' of github.com:gmcquillan/django-brake

  • Loading branch information...
2 parents 277fac9 + d6b864a commit 62224463c20292abe760335000063188244bba89 @gmcquillan committed Feb 25, 2014
Showing with 31 additions and 6 deletions.
  1. +4 −0 README.rst
  2. +1 −1 brake/__init__.py
  3. +7 −3 brake/decorators.py
  4. +17 −1 brake/tests/tests.py
  5. +2 −1 test_settings.py
View
@@ -197,6 +197,10 @@ and override.
class. The class itself should be the last in the chain.
+.. note:: RATELIMIT_STATUS_CODE is another setting you might set if you'd
+ like the decorator to return something other than ``403`` if ``block=True``.
+
+
Internals
---------
View
@@ -1 +1 @@
-VERSION = (1, 2, 4)
+VERSION = (1, 3, 0)
View
@@ -5,7 +5,7 @@
from django.http import HttpResponse
class HttpResponseTooManyRequests(HttpResponse):
- status_code = 429
+ status_code = getattr(settings, 'RATELIMIT_STATUS_CODE', 403)
def _method_match(request, method=None):
if method is None:
@@ -51,7 +51,9 @@ def get_class_by_path(path):
_backend = get_class_by_path(_backend_class)()
-def ratelimit(ip=True, block=False, method=None, field=None, rate='5/m', increment=None):
+def ratelimit(
+ ip=True, block=False, method=None, field=None, rate='5/m', increment=None
+):
def decorator(fn):
func_name = fn.__name__
count, period = _split_rate(rate)
@@ -75,7 +77,9 @@ def _wrapped(request, *args, **kw):
response = fn(request, *args, **kw)
if _method_match(request, method) and \
- (increment is None or (callable(increment) and increment(request, response))):
+ (increment is None or (callable(increment) and increment(
+ request, response
+ ))):
_backend.count(func_name, request, ip, field, period)
return response
View
@@ -1,4 +1,5 @@
from django.core.cache import cache
+from django.http import HttpResponse
from django.utils import unittest
from brake.decorators import ratelimit
@@ -45,6 +46,7 @@ def setUpClass(cls):
# populated in cache.
cls.FUNCTIONS = (
'fake_login',
+ 'fake_login_no_exception',
)
cls.PERIODS = (60, 3600, 86400)
@@ -129,6 +131,13 @@ def fake_login(request):
return True
+@ratelimit(field='username', method='POST', rate='10/m', block=True)
+def fake_login_no_exception(request):
+ """Fake view allows us to examine the response code."""
+ return HttpResponse()
+
+
+
class TestRateLimiting(RateLimitTestCase):
def setUp(self):
@@ -229,7 +238,7 @@ def test_smaller_periods_unaffected_by_larger_periods(self):
self.assertTrue(self.client.post(fake_login, self.good_payload))
def test_overridden_get_ip_works(self):
- """Test that our MyBrake Class defined in test_settings works as expected."""
+ """Test that our MyBrake Class defined in test_settings works."""
cache.set(self.KEYS.fake_login_ip_60, 6)
# Should trigger a ratelimit, but only from the HTTP_TRUE_CLIENT_IP
# REMOTE_ADDR (the default) isn't in our cache at all.
@@ -243,3 +252,10 @@ def test_overridden_get_ip_works(self):
'REMOTE_ADDR': '1.2.3.4'
}
)
+
+ def test_status_code(self):
+ """Test that our custom status code is returned."""
+ cache.set(self.KEYS.fake_login_no_exception_ip_60, 20)
+ result = self.client.post(fake_login_no_exception, self.bad_payload)
+ # The default is 403, if we see 429, then we know our setting worked.
+ self.assertEqual(result.status_code, 429)
View
@@ -20,6 +20,7 @@
}
RATELIMIT_CACHE_BACKEND = 'brake.tests.custom_backend.MyBrake'
+RATELIMIT_STATUS_CODE = 429 # The HTTP Response code to return.
# point to ourselves as the root urlconf, define no patterns (see below)
ROOT_URLCONF = 'test_settings'
@@ -28,6 +29,6 @@
SECRET_KEY = 'HAHAHA ratelimits!'
# turn this file into a pseudo-urls.py.
-from django.conf.urls.defaults import *
+from django.conf.urls import patterns
urlpatterns = patterns('',)

0 comments on commit 6222446

Please sign in to comment.