Skip to content

Commit 2ee34e7

Browse files
authored
feat(aiohttp): Add sentry.is_localhost for inbound filters
1 parent 73bce0d commit 2ee34e7

2 files changed

Lines changed: 87 additions & 0 deletions

File tree

‎sentry_sdk/integrations/aiohttp.py‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
AnnotatedValue,
4747
_get_aws_sigv4_signed_headers_from_authorization_header,
4848
_get_aws_sigv4_signed_headers_from_url_query_string,
49+
_is_localhost,
4950
_register_control_flow_exception,
5051
capture_internal_exceptions,
5152
ensure_integration_enabled,
@@ -146,6 +147,17 @@ async def sentry_app_handle(
146147
scope.clear_breadcrumbs()
147148
scope.add_event_processor(_make_request_processor(weak_request))
148149

150+
scope.set_attribute(
151+
SPANDATA.SENTRY_IS_LOCALHOST,
152+
_is_localhost(
153+
client_ip=_get_client_ip(request),
154+
host_header=request.headers.get("Host"),
155+
forwarded_host_header=request.headers.get(
156+
"X-Forwarded-Host"
157+
),
158+
),
159+
)
160+
149161
headers = dict(request.headers)
150162

151163
span_ctx: "ContextManager[Union[Span, StreamedSpan]]"
@@ -643,6 +655,17 @@ def aiohttp_processor(
643655
return aiohttp_processor
644656

645657

658+
def _get_client_ip(request: "Request") -> "Optional[str]":
659+
x_forwarded_for = request.headers.get("X-Forwarded-For", "").split(",")[0].strip()
660+
if x_forwarded_for:
661+
return x_forwarded_for
662+
663+
if request.headers.get("X-Real-IP"):
664+
return request.headers["X-Real-IP"]
665+
666+
return request.remote
667+
668+
646669
def _capture_exception() -> "ExcInfo":
647670
exc_info = sys.exc_info()
648671
event, hint = event_from_exception(

‎tests/integrations/aiohttp/test_aiohttp.py‎

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2416,6 +2416,70 @@ async def hello(request):
24162416
assert event["request"]["query_string"] == expected_query
24172417

24182418

2419+
@pytest.mark.asyncio
2420+
@pytest.mark.parametrize(
2421+
"host_header, override_remote, is_localhost",
2422+
[
2423+
pytest.param(None, None, True, id="loopback-ip"),
2424+
pytest.param(
2425+
"localhost:8080", "93.184.216.34", True, id="localhost-host-header"
2426+
),
2427+
pytest.param("example.com", "93.184.216.34", False, id="non-local"),
2428+
],
2429+
)
2430+
async def test_is_localhost_attribute(
2431+
sentry_init,
2432+
aiohttp_client,
2433+
capture_items,
2434+
monkeypatch,
2435+
host_header,
2436+
override_remote,
2437+
is_localhost,
2438+
):
2439+
sentry_init(
2440+
integrations=[AioHttpIntegration()],
2441+
traces_sample_rate=1.0,
2442+
trace_lifecycle="stream",
2443+
)
2444+
2445+
async def hello(request):
2446+
with sentry_sdk.traces.start_span(name="child"):
2447+
pass
2448+
return web.Response(text="hello")
2449+
2450+
app = web.Application()
2451+
app.router.add_get("/", hello)
2452+
2453+
if override_remote is not None:
2454+
from aiohttp.web_request import Request as AioRequest
2455+
2456+
original_init = AioRequest.__init__
2457+
2458+
def patched_init(self, *args, **kwargs):
2459+
original_init(self, *args, **kwargs)
2460+
self._transport_peername = (override_remote, 0)
2461+
2462+
monkeypatch.setattr(AioRequest, "__init__", patched_init)
2463+
2464+
items = capture_items("span")
2465+
2466+
client = await aiohttp_client(app)
2467+
headers = {"Host": host_header} if host_header else {}
2468+
resp = await client.get("/", headers=headers)
2469+
assert resp.status == 200
2470+
2471+
sentry_sdk.flush()
2472+
2473+
child_spans = [item.payload for item in items if not item.payload.get("is_segment")]
2474+
server_spans = [item.payload for item in items if item.payload.get("is_segment")]
2475+
2476+
assert len(server_spans) == 1
2477+
assert len(child_spans) == 1
2478+
2479+
assert server_spans[0]["attributes"][SPANDATA.SENTRY_IS_LOCALHOST] == is_localhost
2480+
assert child_spans[0]["attributes"][SPANDATA.SENTRY_IS_LOCALHOST] == is_localhost
2481+
2482+
24192483
@pytest.mark.asyncio
24202484
@pytest.mark.parametrize(
24212485
"init_kwargs, expect_remote_addr", DATA_COLLECTION_REMOTE_ADDR_CASES

0 commit comments

Comments
 (0)