aboutsummaryrefslogtreecommitdiffstats
path: root/djangorestframework/permissions.py
diff options
context:
space:
mode:
authorTom Christie2011-06-15 14:41:09 +0100
committerTom Christie2011-06-15 14:41:09 +0100
commit1cb84cd4e82880caea645ebd99a947cead3096b9 (patch)
tree5ae955f4a7ef5cd9754f2b5c11caecdedcad1f10 /djangorestframework/permissions.py
parentff6e78323f88fd58b1de5b02e2440c2fc24c9c8b (diff)
parent49a2817eb5ccf5f176ff5366d69df3a307dfcda2 (diff)
downloaddjango-rest-framework-1cb84cd4e82880caea645ebd99a947cead3096b9.tar.bz2
Merge throttling and fix up a coupla things
Diffstat (limited to 'djangorestframework/permissions.py')
-rw-r--r--djangorestframework/permissions.py29
1 files changed, 20 insertions, 9 deletions
diff --git a/djangorestframework/permissions.py b/djangorestframework/permissions.py
index 34ab5bf4..7dcabcf0 100644
--- a/djangorestframework/permissions.py
+++ b/djangorestframework/permissions.py
@@ -31,11 +31,6 @@ _503_SERVICE_UNAVAILABLE = ErrorResponse(
{'detail': 'request was throttled'})
-class ConfigurationException(BaseException):
- """To alert for bad configuration decisions as a convenience."""
- pass
-
-
class BasePermission(object):
"""
A base class from which all permission classes should inherit.
@@ -142,14 +137,13 @@ class BaseThrottle(BasePermission):
# Drop any requests from the history which have now passed the
# throttle duration
- while self.history and self.history[0] <= self.now - self.duration:
+ while self.history and self.history[-1] <= self.now - self.duration:
self.history.pop()
-
if len(self.history) >= self.num_requests:
self.throttle_failure()
else:
self.throttle_success()
-
+
def throttle_success(self):
"""
Inserts the current request's timestamp along with the key
@@ -157,13 +151,30 @@ class BaseThrottle(BasePermission):
"""
self.history.insert(0, self.now)
cache.set(self.key, self.history, self.duration)
-
+ header = 'status=SUCCESS; next=%s sec' % self.next()
+ self.view.add_header('X-Throttle', header)
+
def throttle_failure(self):
"""
Called when a request to the API has failed due to throttling.
Raises a '503 service unavailable' response.
"""
+ header = 'status=FAILURE; next=%s sec' % self.next()
+ self.view.add_header('X-Throttle', header)
raise _503_SERVICE_UNAVAILABLE
+
+ def next(self):
+ """
+ Returns the recommended next request time in seconds.
+ """
+ if self.history:
+ remaining_duration = self.duration - (self.now - self.history[-1])
+ else:
+ remaining_duration = self.duration
+
+ available_requests = self.num_requests - len(self.history) + 1
+
+ return '%.2f' % (remaining_duration / float(available_requests))
class PerUserThrottling(BaseThrottle):