diff options
| author | Eoghan Glynn <eglynn@redhat.com> | 2012-02-28 20:22:19 +0000 |
|---|---|---|
| committer | Eoghan Glynn <eglynn@redhat.com> | 2012-02-28 20:26:29 +0000 |
| commit | 8bc87c62a118c75a6cbf69c0edfa3ba5acbf3950 (patch) | |
| tree | 18404b1d64c56797e82e731e95de1c763e703140 | |
| parent | 85f844c26e1a51665891ede3e5696d13433a7c59 (diff) | |
| download | nova-8bc87c62a118c75a6cbf69c0edfa3ba5acbf3950.tar.gz nova-8bc87c62a118c75a6cbf69c0edfa3ba5acbf3950.tar.xz nova-8bc87c62a118c75a6cbf69c0edfa3ba5acbf3950.zip | |
Provide retry-after guidance on throttled requests
Fixes bug 942874
Guide the caller's redrive strategy with a Retry-After hint in
the 413 response emitted when rate limits are exceeded.
The simplest format of Retry-After is used, i.e. number of seconds
as opposed to a HTTP time string.
Change-Id: I8b1a28f964a111008b1a88d9c0f96c5a0abd8314
| -rw-r--r-- | nova/api/openstack/wsgi.py | 12 | ||||
| -rw-r--r-- | nova/tests/api/openstack/compute/test_limits.py | 4 |
2 files changed, 15 insertions, 1 deletions
diff --git a/nova/api/openstack/wsgi.py b/nova/api/openstack/wsgi.py index 8f0259024..047b68956 100644 --- a/nova/api/openstack/wsgi.py +++ b/nova/api/openstack/wsgi.py @@ -18,6 +18,8 @@ import inspect from xml.dom import minidom from xml.parsers import expat +import math +import time from lxml import etree import webob @@ -1075,7 +1077,8 @@ class OverLimitFault(webob.exc.HTTPException): """ Initialize new `OverLimitFault` with relevant information. """ - self.wrapped_exc = webob.exc.HTTPRequestEntityTooLarge() + hdrs = OverLimitFault._retry_after(retry_time) + self.wrapped_exc = webob.exc.HTTPRequestEntityTooLarge(headers=hdrs) self.content = { "overLimitFault": { "code": self.wrapped_exc.status_int, @@ -1084,6 +1087,13 @@ class OverLimitFault(webob.exc.HTTPException): }, } + @staticmethod + def _retry_after(retry_time): + delay = int(math.ceil(retry_time - time.time())) + retry_after = delay if delay > 0 else 0 + headers = {'Retry-After': '%d' % retry_after} + return headers + @webob.dec.wsgify(RequestClass=Request) def __call__(self, request): """ diff --git a/nova/tests/api/openstack/compute/test_limits.py b/nova/tests/api/openstack/compute/test_limits.py index 26e0094c0..eb4ab00c4 100644 --- a/nova/tests/api/openstack/compute/test_limits.py +++ b/nova/tests/api/openstack/compute/test_limits.py @@ -315,6 +315,10 @@ class LimitMiddlewareTest(BaseLimitTestSuite): response = request.get_response(self.app) self.assertEqual(response.status_int, 413) + self.assertTrue('Retry-After' in response.headers) + retry_after = int(response.headers['Retry-After']) + self.assertAlmostEqual(retry_after, 60, 1) + body = json.loads(response.body) expected = "Only 1 GET request(s) can be made to * every minute." value = body["overLimitFault"]["details"].strip() |
