Skip to content

Commit

Permalink
Fixed URLRouter root_path handling. (#1954)
Browse files Browse the repository at this point in the history
* Add tests for handling root_path in URLRouting
* Handle root_path in URLRouter

If we have a scope["root_path"], raise if it does not prefix
scope["path"], and strip it from scope["path"] if it does. Do this
only if we're in an outermost URLRouter.

Signed-off-by: Alejandro R. Sedeño <[email protected]>
Signed-off-by: Alejandro R Sedeño <[email protected]>
  • Loading branch information
asedeno authored Apr 3, 2024
1 parent ecbf353 commit 82c26f2
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 0 deletions.
9 changes: 9 additions & 0 deletions channels/routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,15 @@ async def __call__(self, scope, receive, send):
path = scope.get("path_remaining", scope.get("path", None))
if path is None:
raise ValueError("No 'path' key in connection scope, cannot route URLs")

if "path_remaining" not in scope:
# We are the outermost URLRouter, so handle root_path if present.
root_path = scope.get("root_path", "")
if root_path and not path.startswith(root_path):
# If root_path is present, path must start with it.
raise ValueError("No route found for path %r." % path)
path = path[len(root_path) :]

# Remove leading / to match Django's handling
path = path.lstrip("/")
# Run through the routes we have until one matches
Expand Down
40 changes: 40 additions & 0 deletions tests/test_routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,23 @@ async def test_url_router():
"args": tuple(),
"kwargs": {"default": 42},
}
# Valid root_path in scope
assert (
await router(
{"type": "http", "path": "/root/", "root_path": "/root"}, None, None
)
== 1
)
assert (
await router(
{"type": "http", "path": "/root/foo/", "root_path": "/root"}, None, None
)
== 2
)

# Unmatched root_path in scope
with pytest.raises(ValueError):
await router({"type": "http", "path": "/", "root_path": "/root"}, None, None)

# Invalid matches
with pytest.raises(ValueError):
Expand Down Expand Up @@ -261,6 +278,29 @@ async def test_path_remaining():
== 2
)

assert (
await outermost_router(
{"type": "http", "path": "/root/prefix/stuff/", "root_path": "/root"},
None,
None,
)
== 2
)

with pytest.raises(ValueError):
await outermost_router(
{"type": "http", "path": "/root/root/prefix/stuff/", "root_path": "/root"},
None,
None,
)

with pytest.raises(ValueError):
await outermost_router(
{"type": "http", "path": "/root/prefix/root/stuff/", "root_path": "/root"},
None,
None,
)


def test_invalid_routes():
"""
Expand Down

0 comments on commit 82c26f2

Please sign in to comment.