From 5d0622c461f3374f0e7def919fdae33e596494de Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Wed, 26 Aug 2026 09:27:42 -0400 Subject: [PATCH] fix(litestar): Gate request body collection on data_collection experiment Only attach request body data to events when "incoming_request" is present in the data_collection.http_bodies experiment option (or when the experiment is unset, preserving default behavior). Refs PY-2419 Refs #6283 --- sentry_sdk/integrations/litestar.py | 10 ++- tests/integrations/litestar/test_litestar.py | 74 +++++++++++++++++++- 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/sentry_sdk/integrations/litestar.py b/sentry_sdk/integrations/litestar.py index 8a3f09ffa0..593ac158aa 100644 --- a/sentry_sdk/integrations/litestar.py +++ b/sentry_sdk/integrations/litestar.py @@ -321,6 +321,8 @@ async def handle_wrapper( def event_processor(event: "Event", _: "Hint") -> "Event": request_info = event.get("request", {}) request_info["content_length"] = len(scope.get("_body", b"")) + should_attach_request_body = True + if has_data_collection_enabled(client.options): cookies = _apply_key_value_collection_filtering( items=extracted_request_data["cookies"], @@ -328,9 +330,15 @@ def event_processor(event: "Event", _: "Hint") -> "Event": ) if cookies: request_info["cookies"] = cookies + + should_attach_request_body = ( + "incoming_request" + in client.options["data_collection"]["http_bodies"] + ) elif should_send_default_pii(): request_info["cookies"] = extracted_request_data["cookies"] - if request_data is not None: + + if request_data is not None and should_attach_request_body: request_info["data"] = request_data event["request"] = deepcopy(request_info) diff --git a/tests/integrations/litestar/test_litestar.py b/tests/integrations/litestar/test_litestar.py index 07880aee8f..5453aaec6c 100644 --- a/tests/integrations/litestar/test_litestar.py +++ b/tests/integrations/litestar/test_litestar.py @@ -4,7 +4,7 @@ from typing import Any import pytest -from litestar import Controller, Litestar, get +from litestar import Controller, Litestar, get, post from litestar.exceptions import HTTPException from litestar.logging.config import LoggingConfig from litestar.middleware import AbstractMiddleware @@ -49,6 +49,11 @@ async def message_with_id() -> "dict[str, Any]": capture_message("hi") return {"status": "ok"} + @post("/body/json") + async def body_json(data: "dict[str, Any]") -> "dict[str, Any]": + capture_message("hi") + return {"status": "ok"} + logging_config = LoggingConfig() app = Litestar( @@ -57,6 +62,7 @@ async def message_with_id() -> "dict[str, Any]": custom_error, message, message_with_id, + body_json, MyController, ], debug=debug, @@ -677,6 +683,72 @@ async def __call__(self, scope, receive, send): COOKIE_HEADER = "jwt=tokenval; theme=dark; lang=en; identity=alice" +@pytest.mark.parametrize( + "data_collection, expect_body", + [ + pytest.param(None, True, id="no_data_collection_experiment"), + pytest.param({}, True, id="data_collection_http_bodies_default"), + pytest.param( + {"http_bodies": ["incoming_request"]}, + True, + id="data_collection_http_bodies_incoming_request", + ), + pytest.param( + {"http_bodies": []}, False, id="data_collection_http_bodies_empty" + ), + ], +) +def test_request_body_data_collection( + sentry_init, capture_events, data_collection, expect_body +): + sentry_init( + traces_sample_rate=1.0, + integrations=[LitestarIntegration()], + _experiments=( + {} if data_collection is None else {"data_collection": data_collection} + ), + ) + + litestar_app = litestar_app_factory() + events = capture_events() + + body = {"foo": {"bar": "baz", "qux": ["1", "2", "3"]}} + + client = TestClient(litestar_app) + client.post("/body/json", json=body) + + (event, transaction_event) = events + + if expect_body: + assert event["request"]["data"] == body + assert transaction_event["request"]["data"] == body + else: + assert "data" not in event["request"] + assert "data" not in transaction_event["request"] + + +def test_request_body_data_collection_wins_over_send_default_pii( + sentry_init, capture_events +): + sentry_init( + traces_sample_rate=1.0, + integrations=[LitestarIntegration()], + send_default_pii=True, + _experiments={"data_collection": {"http_bodies": []}}, + ) + + litestar_app = litestar_app_factory() + events = capture_events() + + client = TestClient(litestar_app) + client.post("/body/json", json={"foo": {"bar": "baz", "qux": ["1", "2", "3"]}}) + + (event, transaction_event) = events + + assert "data" not in event["request"] + assert "data" not in transaction_event["request"] + + @pytest.mark.parametrize( "init_kwargs, expected_cookies", [