-
Notifications
You must be signed in to change notification settings - Fork 710
Ensure clean http url #538
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 10 commits
2e8e14f
441a0df
7558742
bf536ad
c8be726
9aba340
358aaa0
f1fb942
b70049d
063759b
62c11fc
685302a
aff0526
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -321,6 +321,37 @@ async def request_handler(request): | |
] | ||
) | ||
|
||
def test_credential_removal(self): | ||
trace_configs = [aiohttp_client.create_trace_config()] | ||
|
||
url = "http://username:[email protected]/status/200" | ||
with self.subTest(url=url): | ||
|
||
async def do_request(url): | ||
async with aiohttp.ClientSession( | ||
trace_configs=trace_configs, | ||
) as session: | ||
async with session.get(url): | ||
pass | ||
|
||
loop = asyncio.get_event_loop() | ||
loop.run_until_complete(do_request(url)) | ||
|
||
self.assert_spans( | ||
[ | ||
( | ||
"HTTP GET", | ||
(StatusCode.UNSET, None), | ||
{ | ||
SpanAttributes.HTTP_METHOD: "GET", | ||
SpanAttributes.HTTP_URL: "http://httpbin.org/status/200", | ||
SpanAttributes.HTTP_STATUS_CODE: int(HTTPStatus.OK), | ||
}, | ||
) | ||
] | ||
) | ||
self.memory_exporter.clear() | ||
|
||
|
||
class TestAioHttpClientInstrumentor(TestBase): | ||
URL = "/test-path" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -430,6 +430,14 @@ def test_response_attributes_invalid_status_code(self): | |
otel_asgi.set_status_code(self.span, "Invalid Status Code") | ||
self.assertEqual(self.span.set_status.call_count, 1) | ||
|
||
def test_credential_removal(self): | ||
self.scope["server"] = ("username:[email protected]", 80) | ||
self.scope["path"] = "/status/200" | ||
attrs = otel_asgi.collect_request_attributes(self.scope) | ||
self.assertEqual( | ||
attrs[SpanAttributes.HTTP_URL], "http://httpbin.org/status/200" | ||
) | ||
|
||
|
||
if __name__ == "__main__": | ||
unittest.main() |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -357,6 +357,13 @@ def test_invalid_url(self): | |
) | ||
self.assertEqual(span.status.status_code, StatusCode.ERROR) | ||
|
||
def test_credential_removal(self): | ||
new_url = "http://username:[email protected]/status/200" | ||
self.perform_request(new_url) | ||
span = self.assert_span() | ||
|
||
self.assertEqual(span.attributes[SpanAttributes.HTTP_URL], self.URL) | ||
|
||
def test_if_headers_equals_none(self): | ||
result = requests.get(self.URL, headers=None) | ||
self.assertEqual(result.text, "Hello!") | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -455,6 +455,29 @@ def test_response_headers(self): | |
self.memory_exporter.clear() | ||
set_global_response_propagator(orig) | ||
|
||
def test_credential_removal(self): | ||
response = self.fetch( | ||
"http://username:[email protected]/status/200" | ||
) | ||
self.assertEqual(response.code, 200) | ||
|
||
spans = self.sorted_spans(self.memory_exporter.get_finished_spans()) | ||
self.assertEqual(len(spans), 1) | ||
client = spans[0] | ||
|
||
self.assertEqual(client.name, "GET") | ||
self.assertEqual(client.kind, SpanKind.CLIENT) | ||
self.assert_span_has_attributes( | ||
client, | ||
{ | ||
SpanAttributes.HTTP_URL: "http://httpbin.org/status/200", | ||
SpanAttributes.HTTP_METHOD: "GET", | ||
SpanAttributes.HTTP_STATUS_CODE: 200, | ||
}, | ||
) | ||
|
||
self.memory_exporter.clear() | ||
|
||
|
||
class TornadoHookTest(TornadoTest): | ||
_client_request_hook = None | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,6 +35,8 @@ | |
from opentelemetry.test.test_base import TestBase | ||
from opentelemetry.trace import StatusCode | ||
|
||
# pylint: disable=too-many-public-methods | ||
|
||
|
||
class RequestsIntegrationTestBase(abc.ABC): | ||
# pylint: disable=no-member | ||
|
@@ -318,6 +320,15 @@ def test_requests_timeout_exception(self, *_, **__): | |
span = self.assert_span() | ||
self.assertEqual(span.status.status_code, StatusCode.ERROR) | ||
|
||
def test_credential_removal(self): | ||
url = "http://username:[email protected]/status/200" | ||
|
||
with self.assertRaises(Exception): | ||
self.perform_request(url) | ||
|
||
span = self.assert_span() | ||
self.assertEqual(span.attributes[SpanAttributes.HTTP_URL], self.URL) | ||
|
||
|
||
class TestRequestsIntegration(RequestsIntegrationTestBase, TestBase): | ||
@staticmethod | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -287,3 +287,9 @@ def url_filter(url): | |
|
||
response = self.perform_request(self.HTTP_URL + "?e=mcc") | ||
self.assert_success_span(response, self.HTTP_URL) | ||
|
||
def test_credential_removal(self): | ||
url = "http://username:[email protected]/status/200" | ||
|
||
response = self.perform_request(url) | ||
self.assert_success_span(response, self.HTTP_URL) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -364,6 +364,18 @@ def test_response_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_credential_removal(self): | ||
self.environ["HTTP_HOST"] = "username:[email protected]" | ||
self.environ["PATH_INFO"] = "/status/200" | ||
expected = { | ||
SpanAttributes.HTTP_URL: "http://httpbin.com/status/200", | ||
SpanAttributes.NET_HOST_PORT: 80, | ||
} | ||
self.assertGreaterEqual( | ||
otel_wsgi.collect_request_attributes(self.environ).items(), | ||
expected.items(), | ||
) | ||
|
||
|
||
class TestWsgiMiddlewareWithTracerProvider(WsgiTestBase): | ||
def validate_response( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ | |
from typing import Dict, Sequence | ||
|
||
from wrapt import ObjectProxy | ||
from yarl import URL | ||
|
||
from opentelemetry.trace import StatusCode | ||
|
||
|
@@ -60,3 +61,12 @@ def unwrap(obj, attr: str): | |
func = getattr(obj, attr, None) | ||
if func and isinstance(func, ObjectProxy) and hasattr(func, "__wrapped__"): | ||
setattr(obj, attr, func.__wrapped__) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would this logic be better off here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only thought I had was that it is most similar to the other utility function There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe the library would be used for all http related instrumentations, it just so happens the logic contained is only used in server instrumentations. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good 👍 Just updated with the last remaining suggestions. |
||
|
||
def remove_url_credentials(url: str) -> str: | ||
"""Given a string url, attempt to remove the username and password""" | ||
try: | ||
url = str(URL(url).with_user(None)) | ||
except ValueError: # invalid url was passed | ||
pass | ||
return url |
Uh oh!
There was an error while loading. Please reload this page.