From 327d29961fd33f28a050a1745b4e3e1cd92b9c1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Neum=C3=BCller?= Date: Wed, 18 Sep 2019 11:08:21 +0200 Subject: [PATCH] wsgi: Fix non-absolute http.url (fixes #143). --- .../src/opentelemetry/ext/wsgi/__init__.py | 33 +++++++++++++++---- .../tests/test_wsgi_middleware.py | 30 +++++++++++++++++ 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/ext/opentelemetry-ext-wsgi/src/opentelemetry/ext/wsgi/__init__.py b/ext/opentelemetry-ext-wsgi/src/opentelemetry/ext/wsgi/__init__.py index a3120c2c0a6..1c1e68ae723 100644 --- a/ext/opentelemetry-ext-wsgi/src/opentelemetry/ext/wsgi/__init__.py +++ b/ext/opentelemetry-ext-wsgi/src/opentelemetry/ext/wsgi/__init__.py @@ -20,6 +20,7 @@ import functools import wsgiref.util as wsgiref_util +from urllib.parse import urlparse from opentelemetry import trace from opentelemetry.ext.wsgi.version import __version__ # noqa @@ -47,13 +48,33 @@ def _add_request_attributes(span, environ): span.set_attribute("http.method", environ["REQUEST_METHOD"]) host = environ.get("HTTP_HOST") or environ["SERVER_NAME"] - span.set_attribute("http.host", host) + span.set_attribute("http.host", host) # NOTE: Nonstandard. + + url = environ.get("REQUEST_URI") or environ.get("RAW_URI") + + if url: # We got something, but is absolute? + # The simplistic ``"://" in url` is not sufficient, + # as that could be contained in the query string. + try: + urlparts = urlparse(url) + except Exception: # pylint:disable=broad-except + url = wsgiref_util.request_uri(environ) + else: + if not urlparts.netloc: + scheme = environ["wsgi.url_scheme"] + portstr = "" + if scheme == "https": + if environ.get("SERVER_PORT", "443") != "443": + portstr = ":" + environ["SERVER_PORT"] + elif environ.get("SERVER_PORT", "80") != "80": + portstr = ":" + environ["SERVER_PORT"] + + url = ( + scheme + "://" + (host or "localhost") + portstr + url + ) + else: + url = wsgiref_util.request_uri(environ) - url = ( - environ.get("REQUEST_URI") - or environ.get("RAW_URI") - or wsgiref_util.request_uri(environ, include_query=False) - ) span.set_attribute("http.url", url) @staticmethod diff --git a/ext/opentelemetry-ext-wsgi/tests/test_wsgi_middleware.py b/ext/opentelemetry-ext-wsgi/tests/test_wsgi_middleware.py index 73bba504523..9270772a1b7 100644 --- a/ext/opentelemetry-ext-wsgi/tests/test_wsgi_middleware.py +++ b/ext/opentelemetry-ext-wsgi/tests/test_wsgi_middleware.py @@ -171,6 +171,36 @@ def test_request_attributes(self): self.assertEqual(self.span.set_attribute.call_count, len(expected)) self.span.set_attribute.assert_has_calls(expected, any_order=True) + def test_request_attributes_with_partial_raw_uri(self): + self.environ["RAW_URI"] = "/#top" + OpenTelemetryMiddleware._add_request_attributes( # noqa pylint: disable=protected-access + self.span, self.environ + ) + self.span.set_attribute.assert_any_call( + "http.url", "http://127.0.0.1/#top" + ) + + def test_request_attributes_with_partial_raw_uri_and_nonstandard_port( + self + ): + self.environ["RAW_URI"] = "/#top" + self.environ["SERVER_PORT"] = "8080" + OpenTelemetryMiddleware._add_request_attributes( # noqa pylint: disable=protected-access + self.span, self.environ + ) + self.span.set_attribute.assert_any_call( + "http.url", "http://127.0.0.1:8080/#top" + ) + + def test_request_attributes_with_full_request_uri(self): + self.environ["REQUEST_URI"] = "http://foobar.com:8080/?foo=bar#top" + OpenTelemetryMiddleware._add_request_attributes( # noqa pylint: disable=protected-access + self.span, self.environ + ) + self.span.set_attribute.assert_any_call( + "http.url", "http://foobar.com:8080/?foo=bar#top" + ) + def test_response_attributes(self): OpenTelemetryMiddleware._add_response_attributes( # noqa pylint: disable=protected-access self.span, "404 Not Found"