From f5ef1a34c1ef799b807b4deeac4b66a5e3fcc873 Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Tue, 19 May 2026 09:02:19 +0200 Subject: [PATCH] test(fastapi): Verify request info captured with POST endpoints --- tests/integrations/fastapi/photo.jpg | Bin 0 -> 21014 bytes tests/integrations/fastapi/test_fastapi.py | 154 ++++++++++++++++++++- 2 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 tests/integrations/fastapi/photo.jpg diff --git a/tests/integrations/fastapi/photo.jpg b/tests/integrations/fastapi/photo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..52fbeef721973389ab1d83fe7f81b511c07cb633 GIT binary patch literal 21014 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 R$o+56eGlcU$KL$w|Ji#B2Ydhk literal 0 HcmV?d00001 diff --git a/tests/integrations/fastapi/test_fastapi.py b/tests/integrations/fastapi/test_fastapi.py index 25f27e2f49..845b948e71 100644 --- a/tests/integrations/fastapi/test_fastapi.py +++ b/tests/integrations/fastapi/test_fastapi.py @@ -1,5 +1,7 @@ +import base64 import json import logging +import os import threading import warnings from unittest import mock @@ -7,7 +9,7 @@ import fastapi import pytest import starlette -from fastapi import FastAPI, HTTPException, Request +from fastapi import Body, FastAPI, File, Form, HTTPException, Request, UploadFile from fastapi.middleware.trustedhost import TrustedHostMiddleware from fastapi.testclient import TestClient @@ -22,6 +24,28 @@ FASTAPI_VERSION = parse_version(fastapi.__version__) STARLETTE_VERSION = parse_version(starlette.__version__) +PICTURE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "photo.jpg") + +BODY_JSON = {"some": "json", "for": "testing", "nested": {"numbers": 123}} + +BODY_FORM = """--fd721ef49ea403a6\r\nContent-Disposition: form-data; name="username"\r\n\r\nJane\r\n--fd721ef49ea403a6\r\nContent-Disposition: form-data; name="password"\r\n\r\nhello123\r\n--fd721ef49ea403a6\r\nContent-Disposition: form-data; name="photo"; filename="photo.jpg"\r\nContent-Type: image/jpg\r\nContent-Transfer-Encoding: base64\r\n\r\n{{image_data}}\r\n--fd721ef49ea403a6--\r\n""".replace( + "{{image_data}}", str(base64.b64encode(open(PICTURE, "rb").read())) +) + +PARSED_FORM = starlette.datastructures.FormData( + [ + ("username", "Jane"), + ("password", "hello123"), + ( + "photo", + starlette.datastructures.UploadFile( + filename="photo.jpg", + file=open(PICTURE, "rb"), + ), + ), + ] +) + from tests.integrations.conftest import parametrize_test_configurable_status_codes from tests.integrations.starlette import test_starlette @@ -70,9 +94,137 @@ async def _thread_ids_async(): "active": str(threading.current_thread().ident), } + @app.post("/body/json") + async def body_json(payload: dict = Body(...)): + capture_message("hi") + return {"status": "ok"} + + @app.post("/body/form") + async def body_form( + username: str = Form(...), + password: str = Form(...), + photo: UploadFile = File(...), + ): + capture_message("hi") + return {"status": "ok"} + return app +@pytest.mark.asyncio +async def test_request_info_json_body(sentry_init, capture_events): + sentry_init( + traces_sample_rate=1.0, + send_default_pii=True, + integrations=[StarletteIntegration()], + ) + + app = fastapi_app_factory() + client = TestClient(app) + + events = capture_events() + + client.post( + "/body/json", + json=BODY_JSON, + headers={ + "cookie": "yummy_cookie=choco; tasty_cookie=strawberry", + }, + ) + + (event, transaction_event) = events + + assert event["request"]["cookies"] == { + "tasty_cookie": "strawberry", + "yummy_cookie": "choco", + } + assert event["request"]["data"] == BODY_JSON + + assert transaction_event["request"]["cookies"] == { + "tasty_cookie": "strawberry", + "yummy_cookie": "choco", + } + assert transaction_event["request"]["data"] == BODY_JSON + + +@pytest.mark.asyncio +async def test_formdata_request_body(sentry_init, capture_events): + sentry_init( + traces_sample_rate=1.0, + send_default_pii=True, + max_request_body_size="always", + integrations=[StarletteIntegration()], + ) + + app = fastapi_app_factory() + client = TestClient(app) + + events = capture_events() + + client.post( + "/body/form", + data=BODY_FORM.encode("utf-8"), + headers={ + "content-type": "multipart/form-data; boundary=fd721ef49ea403a6", + }, + ) + + (event, transaction_event) = events + assert event["request"]["data"].keys() == PARSED_FORM.keys() + assert event["request"]["data"]["username"] == PARSED_FORM["username"] + assert event["request"]["data"]["password"] == "[Filtered]" + assert event["request"]["data"]["photo"] == "" + assert event["_meta"]["request"]["data"]["photo"] == {"": {"rem": [["!raw", "x"]]}} + + assert transaction_event["request"]["data"].keys() == PARSED_FORM.keys() + assert transaction_event["request"]["data"]["username"] == PARSED_FORM["username"] + assert transaction_event["request"]["data"]["password"] == "[Filtered]" + assert transaction_event["request"]["data"]["photo"] == "" + assert transaction_event["_meta"]["request"]["data"]["photo"] == { + "": {"rem": [["!raw", "x"]]} + } + + +@pytest.mark.asyncio +async def test_request_body_too_big(sentry_init, capture_events): + sentry_init( + traces_sample_rate=1.0, + send_default_pii=True, + integrations=[StarletteIntegration()], + ) + + app = fastapi_app_factory() + client = TestClient(app) + + events = capture_events() + + client.post( + "/body/form", + data=BODY_FORM.encode("utf-8"), + headers={ + "content-type": "multipart/form-data; boundary=fd721ef49ea403a6", + "cookie": "yummy_cookie=choco; tasty_cookie=strawberry", + }, + ) + + (event, transaction_event) = events + assert event["request"]["cookies"] == { + "tasty_cookie": "strawberry", + "yummy_cookie": "choco", + } + # Because request is too big only the AnnotatedValue is extracted. + assert event["_meta"]["request"]["data"] == {"": {"rem": [["!config", "x"]]}} + + assert transaction_event["request"]["cookies"] == { + "tasty_cookie": "strawberry", + "yummy_cookie": "choco", + } + # Because request is too big only the AnnotatedValue is extracted. + assert transaction_event["_meta"]["request"]["data"] == { + "": {"rem": [["!config", "x"]]} + } + + @pytest.mark.asyncio async def test_response(sentry_init, capture_events): # FastAPI is heavily based on Starlette so we also need