fix(starlette): Stop duplicating scope["root_path"] in URLs#6579
Conversation
Codecov Results 📊✅ 89950 passed | ⏭️ 6240 skipped | Total: 96190 | Pass Rate: 93.51% | Execution Time: 321m 17s 📊 Comparison with Base Branch
All tests are passing successfully. ✅ Patch coverage is 96.43%. Project has 2405 uncovered lines. Files with missing lines (1)
Coverage diff@@ Coverage Diff @@
## main #PR +/-##
==========================================
- Coverage 89.93% 89.90% -0.03%
==========================================
Files 192 192 —
Lines 23784 23801 +17
Branches 8210 8214 +4
==========================================
+ Hits 21389 21396 +7
- Misses 2395 2405 +10
- Partials 1342 1345 +3Generated by Codecov Action |
scope["root_path"] in URLs
wahajahmed010
left a comment
There was a problem hiding this comment.
Review: #6579
Summary: Clean fix for ASGI URL duplication when scope["root_path"] is already included in scope["path"]. The approach is sound — thread a path_includes_root_path boolean through the URL construction pipeline.
✅ What works well
- Backward compatible — default is
True, preserving existing behavior for frameworks that don't include root_path in path - Framework-specific handling — correctly version-gated for Starlette (>=0.33), Quart (>=0.19), and hardcoded for Litestar/Starlite
- Test coverage — all 6 integrations tested (Django ASGI, FastAPI, Litestar, Quart, Starlette, Starlite), both span streaming and static lifecycle modes
- Clean threading — parameter flows through
_get_url→_get_request_data→_get_request_attributes→_get_transaction_name_and_source→_get_segment_name_and_source
⚠️ Potential issues
- Django ASGI test — The test sets
comm.scope["root_path"] = "/root"but Django defaults topath_includes_root_path=True. Does Django ASGI actually include root_path in path? If not, this test might pass but produce incorrect URLs in production. Worth verifying Django's ASGI behavior. - No test for
path_includes_root_path=False— The Starlette/FastAPI tests only exercise theTruepath (Starlette >= 0.33). The old behavior (False) has no dedicated test. - Edge case: empty path — When
path_includes_root_path=Trueandscope["path"]is empty, the URL would be just scheme+host with no path. Unlikely but worth noting.
Verdict
Solid PR. The core logic is correct and well-structured. The main risk is the Django default assumption — worth double-checking before merging.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit a96d284. Configure here.
scope["root_path"] in URLsscope["root_path"] in URLs
scope["root_path"] in URLsscope["root_path"] in URLs
There was a problem hiding this comment.
url.path attribute always prepends root_path, ignoring path_includes_root_path
In _get_request_attributes() (_asgi_common.py ~line 152), attributes["url.path"] is always set to root_path + path regardless of path_includes_root_path. For frameworks where path_includes_root_path=True (e.g. Starlette >= 0.33), this re-introduces the exact duplication the PR is trying to fix, just for the url.path span attribute.
Evidence
_get_request_attributesacceptspath_includes_root_pathand correctly passes it to_get_url()forurl.full.- However,
attributes["url.path"] = asgi_scope.get("root_path", "") + asgi_scope.get("path", "")at ~line 152 unconditionally concatenatesroot_pathandpath. - When Starlette >= 0.33 sets
path_includes_root_path=True(starlette.py line 148),scope["path"]already containsroot_path, so this expression doubles the root path segment. _get_url()at line 45 correctly guards withif path_includes_root_path, showing the intended pattern was not applied consistently.
Identified by Warden code-review
There was a problem hiding this comment.
No tests covering the new root_path_in_path behavior in any of the changed test files
The PR description states tests were added for root_path handling in each ASGI integration, but none of the changed test files (test_asgi.py, test_fastapi.py, test_starlette.py) contain any tests exercising root_path or the EITHER/EXCLUDED enum paths. Have you considered adding at least one test that sets root_path in the ASGI scope and asserts the resulting URL is not duplicated?
Evidence
grep -r 'root_path' tests/integrations/asgi/test_asgi.pyreturns no matches.grep -r 'root_path' tests/integrations/starlette/test_starlette.pyreturns no matches.grep -r 'root_path' tests/integrations/fastapi/test_fastapi.pyreturns no matches.- The
_RootPathInPath.EITHERbranch in_get_path(used for Starlette >= 0.33) has detection logic (path.startswith(root_path + "/"),path == root_path) with no test coverage to verify correctness. - The Starlette integration selects
EITHERorEXCLUDEDbased on version at line 149–151 ofstarlette.py, but neither path has an integration-level test withroot_pathset.
Identified by Warden code-review

Description
Add the
root_path_in_pathparameter to_get_url()and related functions.If
root_path_in_pathis_RootPathInPath.EXCLUDED, the existing behavior that prependsscope["root_path"]when forming the url is preserved.The other
_RootPathInPath.EITHERoption is used by the Starlette integration. It preserves Starlette’s behavior of accepting ASGI scopes wherescope["path"]either includesscope["root_path"]or is already relative to it, using heuristics that match the libraries logic.Issues
Closes #6577
Reminders
uv run ruff.feat:,fix:,ref:,meta:)