fix(starlette): Stop duplicating scope["root_path"] in URLs#6579
4 issues
code-review: Found 4 issues (3 medium, 1 low)
Medium
test_request_url fails on Django < 5.1 due to incorrect root_path setup - `sentry_sdk/integrations/django/asgi.py:103`
The new test_request_url test sets scope["path"] = "/root/nomessage" with scope["root_path"] = "/root" (path already includes root_path), but only skips for Django < 3.0. On Django < 5.1, path_includes_root_path=False causes the URL to be constructed as root_path + path = "/root/root/nomessage", which will fail the assertion == "/root/nomessage". Consider adding @pytest.mark.skipif(django.VERSION < (5, 1), ...) or adding a separate test case for the pre-5.1 path format.
Also found at:
tests/integrations/django/asgi/test_asgi.py:1093-1101
Sentry monitoring silently disabled when Quart package version cannot be determined - `sentry_sdk/integrations/quart.py:95-100`
When package_version("quart") returns None (e.g., Quart installed from source without version metadata), the new early-return guard silently skips the SentryAsgiMiddleware entirely, disabling all error capture and tracing for the application. Consider defaulting to path_includes_root_path=False (the pre-spec behavior) instead of bypassing the middleware.
test_request_url doesn't exercise the root_path duplication bug for Starlette - `tests/integrations/starlette/test_starlette.py:1486-1525`
The test uses TestClient with the default root_path="", so the outer ASGI scope always has an empty root_path. The Sentry middleware (guarded by _asgi_middleware_applied) only processes this outer scope, meaning root_path + path and path produce the same URL regardless of whether path_includes_root_path is True or False. The bug (duplication when root_path is non-empty and Starlette >= 0.33 includes it in path) is never triggered. Compare to the Django ASGI test, which correctly sets comm.scope["root_path"] = "/root" with path = "/root/nomessage" to verify no duplication. The Starlette test should use TestClient(starlette_app, root_path="/root") with a request to /nomessage and assert the URL is http://testserver/root/nomessage, not http://testserver/root/root/nomessage.
Low
New default `path_includes_root_path=True` changes URL behavior for direct `SentryAsgiMiddleware` users on non-spec-compliant ASGI apps - `sentry_sdk/integrations/asgi.py:120`
The previous behavior always prepended scope["root_path"] to scope["path"] when building URLs (equivalent to path_includes_root_path=False). The new default True assumes path already includes root_path, which is the ASGI-spec-compliant behavior and fixes a duplication bug for compliant apps. However, users who wrap a non-spec-compliant ASGI app (e.g. old Starlette, Starlite, LiteStar, old Quart) directly with SentryAsgiMiddleware — rather than via the bundled integrations — will now silently get URLs that omit the root_path prefix when root_path is non-empty. The bundled integrations pass path_includes_root_path=False for these frameworks, but direct middleware users have no automatic protection and the new parameter is not documented in the __init__ docstring. This is a narrow backwards-compatibility regression (only manifests with a non-empty root_path on a non-compliant app wrapped directly).
⏱ 6m 29s · 1.9M in / 95.7k out · $3.37
Annotations
Check warning on line 103 in sentry_sdk/integrations/django/asgi.py
sentry-warden / warden: code-review
test_request_url fails on Django < 5.1 due to incorrect root_path setup
The new `test_request_url` test sets `scope["path"] = "/root/nomessage"` with `scope["root_path"] = "/root"` (path already includes root_path), but only skips for Django < 3.0. On Django < 5.1, `path_includes_root_path=False` causes the URL to be constructed as `root_path + path = "/root/root/nomessage"`, which will fail the assertion `== "/root/nomessage"`. Consider adding `@pytest.mark.skipif(django.VERSION < (5, 1), ...)` or adding a separate test case for the pre-5.1 path format.
Check warning on line 1101 in tests/integrations/django/asgi/test_asgi.py
sentry-warden / warden: code-review
[GNZ-9Q4] test_request_url fails on Django < 5.1 due to incorrect root_path setup (additional location)
The new `test_request_url` test sets `scope["path"] = "/root/nomessage"` with `scope["root_path"] = "/root"` (path already includes root_path), but only skips for Django < 3.0. On Django < 5.1, `path_includes_root_path=False` causes the URL to be constructed as `root_path + path = "/root/root/nomessage"`, which will fail the assertion `== "/root/nomessage"`. Consider adding `@pytest.mark.skipif(django.VERSION < (5, 1), ...)` or adding a separate test case for the pre-5.1 path format.
Check warning on line 100 in sentry_sdk/integrations/quart.py
sentry-warden / warden: code-review
Sentry monitoring silently disabled when Quart package version cannot be determined
When `package_version("quart")` returns `None` (e.g., Quart installed from source without version metadata), the new early-return guard silently skips the `SentryAsgiMiddleware` entirely, disabling all error capture and tracing for the application. Consider defaulting to `path_includes_root_path=False` (the pre-spec behavior) instead of bypassing the middleware.
Check warning on line 1525 in tests/integrations/starlette/test_starlette.py
sentry-warden / warden: code-review
test_request_url doesn't exercise the root_path duplication bug for Starlette
The test uses `TestClient` with the default `root_path=""`, so the outer ASGI scope always has an empty `root_path`. The Sentry middleware (guarded by `_asgi_middleware_applied`) only processes this outer scope, meaning `root_path + path` and `path` produce the same URL regardless of whether `path_includes_root_path` is `True` or `False`. The bug (duplication when `root_path` is non-empty and Starlette >= 0.33 includes it in `path`) is never triggered. Compare to the Django ASGI test, which correctly sets `comm.scope["root_path"] = "/root"` with `path = "/root/nomessage"` to verify no duplication. The Starlette test should use `TestClient(starlette_app, root_path="/root")` with a request to `/nomessage` and assert the URL is `http://testserver/root/nomessage`, not `http://testserver/root/root/nomessage`.