summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Dague <sean@dague.net>2017-05-15 07:33:07 -0400
committerSean Dague <sean@dague.net>2017-05-23 12:48:41 -0400
commit9b94bae73c1cf5549a69e7798d175119cc1aaa2e (patch)
tree81f4942c138a1fc23a29ceae1c1630d791e1f439
parent2eaf1ebaf59500ca549fc97c5703f15cda78c801 (diff)
downloadoslo-middleware-9b94bae73c1cf5549a69e7798d175119cc1aaa2e.tar.gz
Allow compatibility headers for request_id
We discovered that Nova is using a local version of the request_id header code because it's x-compute-request-id predates x-openstack-request-id, and things were never migrated after the oslo code was extracted. In order to let Nova use the base code (which may become more complicated with inbound request-id setting) we need to support a compat headers field, which is additional http header names that should be set with the request-id value. Change-Id: I18a92f8bf2f85fcf30d32be68bae58f64b135df0
-rw-r--r--oslo_middleware/request_id.py14
-rw-r--r--oslo_middleware/tests/test_request_id.py26
-rw-r--r--releasenotes/notes/compat_headers-55a635b8ec01b6f1.yaml7
3 files changed, 45 insertions, 2 deletions
diff --git a/oslo_middleware/request_id.py b/oslo_middleware/request_id.py
index 31a433b..5716c82 100644
--- a/oslo_middleware/request_id.py
+++ b/oslo_middleware/request_id.py
@@ -30,11 +30,21 @@ class RequestId(base.ConfigurableMiddleware):
request environment. The request ID is also added to API response.
"""
+ # if compat_headers is set, we also return the request_id in those
+ # headers as well. This allows projects like Nova to adopt
+ # oslo.middleware without impacting existing users.
+ compat_headers = []
+
@webob.dec.wsgify
def __call__(self, req):
req_id = context.generate_request_id()
req.environ[ENV_REQUEST_ID] = req_id
response = req.get_response(self.application)
- if HTTP_RESP_HEADER_REQUEST_ID not in response.headers:
- response.headers.add(HTTP_RESP_HEADER_REQUEST_ID, req_id)
+
+ return_headers = [HTTP_RESP_HEADER_REQUEST_ID]
+ return_headers.extend(self.compat_headers)
+
+ for header in return_headers:
+ if header not in response.headers:
+ response.headers.add(header, req_id)
return response
diff --git a/oslo_middleware/tests/test_request_id.py b/oslo_middleware/tests/test_request_id.py
index 039b7af..5c79c21 100644
--- a/oslo_middleware/tests/test_request_id.py
+++ b/oslo_middleware/tests/test_request_id.py
@@ -22,6 +22,10 @@ import webob.dec
from oslo_middleware import request_id
+class AltHeader(request_id.RequestId):
+ compat_headers = ["x-compute-req-id", "x-silly-id"]
+
+
class RequestIdTest(test_base.BaseTestCase):
def test_generate_request_id(self):
@webob.dec.wsgify
@@ -37,3 +41,25 @@ class RequestIdTest(test_base.BaseTestCase):
self.assertThat(res_req_id, matchers.StartsWith('req-'))
# request-id in request environ is returned as response body
self.assertEqual(res.body.decode('utf-8'), res_req_id)
+
+ def test_compat_headers(self):
+ """Test that compat headers are set
+
+ Compat headers might exist on a super class to support
+ previous API contracts. This ensures that you can set that to
+ a list of headers and those values are the same as the
+ request_id.
+
+ """
+ @webob.dec.wsgify
+ def application(req):
+ return req.environ[request_id.ENV_REQUEST_ID]
+
+ app = AltHeader(application)
+ req = webob.Request.blank('/test')
+ res = req.get_response(app)
+
+ res_req_id = res.headers.get(request_id.HTTP_RESP_HEADER_REQUEST_ID)
+
+ self.assertEqual(res.headers.get("x-compute-req-id"), res_req_id)
+ self.assertEqual(res.headers.get("x-silly-id"), res_req_id)
diff --git a/releasenotes/notes/compat_headers-55a635b8ec01b6f1.yaml b/releasenotes/notes/compat_headers-55a635b8ec01b6f1.yaml
new file mode 100644
index 0000000..489b33c
--- /dev/null
+++ b/releasenotes/notes/compat_headers-55a635b8ec01b6f1.yaml
@@ -0,0 +1,7 @@
+---
+features:
+ - |
+ This adds a new ``compat_headers`` class attribute to the
+ ``RequestId`` middleware. That allows projects like Nova that have
+ API contracts on alternative request-id headers to adopt the oslo
+ ``RequestId`` middleware but still retain their API contract.