diff --git a/rest_framework/exceptions.py b/rest_framework/exceptions.py index 5f774a9f3..389032bd7 100644 --- a/rest_framework/exceptions.py +++ b/rest_framework/exceptions.py @@ -71,7 +71,7 @@ class UnsupportedMediaType(APIException): class Throttled(APIException): status_code = status.HTTP_429_TOO_MANY_REQUESTS default_detail = 'Request was throttled.' - extra_detail = "Expected available in %d second%s." + extra_detail = " Expected available in %d second%s." def __init__(self, wait=None, detail=None): if wait is None: diff --git a/rest_framework/tests/test_throttling.py b/rest_framework/tests/test_throttling.py index 41bff6926..b5ae02cd0 100644 --- a/rest_framework/tests/test_throttling.py +++ b/rest_framework/tests/test_throttling.py @@ -117,8 +117,10 @@ class ThrottlingTests(TestCase): response = view.as_view()(request) if expect is not None: self.assertEqual(response['X-Throttle-Wait-Seconds'], expect) + self.assertEqual(response['Retry-After'], expect) else: self.assertFalse('X-Throttle-Wait-Seconds' in response) + self.assertFalse('Retry-After' in response) def test_seconds_fields(self): """ @@ -165,11 +167,13 @@ class ThrottlingTests(TestCase): response = MockView_NonTimeThrottling.as_view()(request) self.assertFalse('X-Throttle-Wait-Seconds' in response) + self.assertFalse('Retry-After' in response) self.assertTrue(MockView_NonTimeThrottling.throttle_classes[0].called) response = MockView_NonTimeThrottling.as_view()(request) self.assertFalse('X-Throttle-Wait-Seconds' in response) + self.assertFalse('Retry-After' in response) class ScopedRateThrottleTests(TestCase): diff --git a/rest_framework/views.py b/rest_framework/views.py index a2668f2c0..d6ccb301f 100644 --- a/rest_framework/views.py +++ b/rest_framework/views.py @@ -61,6 +61,7 @@ def exception_handler(exc): headers['WWW-Authenticate'] = exc.auth_header if getattr(exc, 'wait', None): headers['X-Throttle-Wait-Seconds'] = '%d' % exc.wait + headers['Retry-After'] = '%d' % exc.wait return Response({'detail': exc.detail}, status=exc.status_code,