diff options
author | Sean Dague <sean@dague.net> | 2017-05-23 07:37:10 -0400 |
---|---|---|
committer | Sean Dague <sean@dague.net> | 2017-05-23 12:48:41 -0400 |
commit | 0e3dbba0d9d373fbfa9e28897cd33377e2491d32 (patch) | |
tree | 82ba63d04c9522b04516a822ef01ff6048446dde | |
parent | 9b94bae73c1cf5549a69e7798d175119cc1aaa2e (diff) | |
download | oslo-middleware-0e3dbba0d9d373fbfa9e28897cd33377e2491d32.tar.gz |
Set global_request_id if passed in as X-OpenStack-Request-ID.
If an inbound header that validates against the regex ``req-$uuid`` is
passed in, we'll set it where oslo.context could later read it. This
creates a mechanism for parents to pass their request-id to children.
Change-Id: I5c5268e8680392395fbe04efe0124575ad8db468
-rw-r--r-- | oslo_middleware/request_id.py | 16 | ||||
-rw-r--r-- | oslo_middleware/tests/test_request_id.py | 41 | ||||
-rw-r--r-- | releasenotes/notes/global_request_id-a8ec7260fbd76444.yaml | 8 |
3 files changed, 65 insertions, 0 deletions
diff --git a/oslo_middleware/request_id.py b/oslo_middleware/request_id.py index 5716c82..9003fa5 100644 --- a/oslo_middleware/request_id.py +++ b/oslo_middleware/request_id.py @@ -13,6 +13,8 @@ # License for the specific language governing permissions and limitations # under the License. +import re + from oslo_context import context import webob.dec @@ -20,7 +22,11 @@ from oslo_middleware import base ENV_REQUEST_ID = 'openstack.request_id' +GLOBAL_REQ_ID = 'openstack.global_request_id' HTTP_RESP_HEADER_REQUEST_ID = 'x-openstack-request-id' +INBOUND_HEADER = 'X-Openstack-Request-Id' +ID_FORMAT = (r'^req-[a-f0-9]{8}-[a-f0-9]{4}-' + r'[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$') class RequestId(base.ConfigurableMiddleware): @@ -35,8 +41,18 @@ class RequestId(base.ConfigurableMiddleware): # oslo.middleware without impacting existing users. compat_headers = [] + def set_global_req_id(self, req): + gr_id = req.headers.get(INBOUND_HEADER, "") + if re.match(ID_FORMAT, gr_id): + req.environ[GLOBAL_REQ_ID] = gr_id + # TODO(sdague): it would be nice to warn if we dropped a bogus + # request_id, but the infrastructure for doing that isn't yet + # setup at this stage. + @webob.dec.wsgify def __call__(self, req): + self.set_global_req_id(req) + req_id = context.generate_request_id() req.environ[ENV_REQUEST_ID] = req_id response = req.get_response(self.application) diff --git a/oslo_middleware/tests/test_request_id.py b/oslo_middleware/tests/test_request_id.py index 5c79c21..5374fa2 100644 --- a/oslo_middleware/tests/test_request_id.py +++ b/oslo_middleware/tests/test_request_id.py @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. +import uuid from oslotest import base as test_base from testtools import matchers @@ -63,3 +64,43 @@ class RequestIdTest(test_base.BaseTestCase): self.assertEqual(res.headers.get("x-compute-req-id"), res_req_id) self.assertEqual(res.headers.get("x-silly-id"), res_req_id) + + def test_global_request_id_set(self): + """Test that global request_id is set.""" + @webob.dec.wsgify + def application(req): + return req.environ[request_id.GLOBAL_REQ_ID] + + global_req = "req-%s" % uuid.uuid4() + app = request_id.RequestId(application) + req = webob.Request.blank( + '/test', + headers={"X-OpenStack-Request-ID": global_req}) + res = req.get_response(app) + res_req_id = res.headers.get(request_id.HTTP_RESP_HEADER_REQUEST_ID) + if isinstance(res_req_id, bytes): + res_req_id = res_req_id.decode('utf-8') + # global-request-id in request environ is returned as response body + self.assertEqual(res.body.decode('utf-8'), global_req) + self.assertNotEqual(res.body.decode('utf-8'), res_req_id) + + def test_global_request_id_drop(self): + """Test that bad format ids are dropped. + + This ensures that badly formatted ids are dropped entirely. + """ + @webob.dec.wsgify + def application(req): + return req.environ.get(request_id.GLOBAL_REQ_ID) + + global_req = "req-%s-bad" % uuid.uuid4() + app = request_id.RequestId(application) + req = webob.Request.blank( + '/test', + headers={"X-OpenStack-Request-ID": global_req}) + res = req.get_response(app) + res_req_id = res.headers.get(request_id.HTTP_RESP_HEADER_REQUEST_ID) + if isinstance(res_req_id, bytes): + res_req_id = res_req_id.decode('utf-8') + # global-request-id in request environ is returned as response body + self.assertEqual(res.body.decode('utf-8'), '') diff --git a/releasenotes/notes/global_request_id-a8ec7260fbd76444.yaml b/releasenotes/notes/global_request_id-a8ec7260fbd76444.yaml new file mode 100644 index 0000000..335a76d --- /dev/null +++ b/releasenotes/notes/global_request_id-a8ec7260fbd76444.yaml @@ -0,0 +1,8 @@ +--- +features: + - | + This adds support for ``global_request_id`` to the ``RequestId`` + middleware. An inbound header of ``X-OpenStack-Request-ID`` is + accepted as long as it is of the format ``req-$uuid``, and made + available to oslo.context. This will allow for cross project + request id tracking. |