Repository: litestar-org/litestar

Issue:
Bug: route with path parameters matches longer paths
### Description

A route registered for `/{param:str}`, in addition to matching `/foo` matches also `/foo/bar` (but not `/foo/bar/baz`).

### URL to code causing the issue

_No response_

### MCVE

```python
from litestar import Litestar, get


@get("/{name:str}")
async def hello_world(name: str) -> str:
    return f"Hello, {name}!"


app = Litestar([hello_world])
```


### Steps to reproduce

```bash
✗ http -b 'localhost:8000/jon'
Hello, jon!


✗ http -b 'localhost:8000/jon/bon'
Hello, jon!


✗ http -b 'localhost:8000/jon/bon/jovi'
{
    "detail": "Not Found",
    "status_code": 404
}
```
```


### Screenshots

```bash
"![SCREENSHOT_DESCRIPTION](SCREENSHOT_LINK.png)"
```


### Logs

_No response_

### Litestar Version

Main branch

### Platform

- [ ] Linux
- [ ] Mac
- [ ] Windows
- [ ] Other (Please specify in the description above)

<!-- POLAR PLEDGE BADGE START -->
## Funding
* If you would like to see an issue prioritized, make a pledge towards it!
* We receive the pledge once the issue is completed & verified

<a href="https://polar.sh/litestar-org/litestar/issues/1830">
<picture>
  <source media="(prefers-color-scheme: dark)" srcset="https://polar.sh/api/github/litestar-org/litestar/issues/1830/pledge.svg?darkmode=1">
  <img alt="Fund with Polar" src="https://polar.sh/api/github/litestar-org/litestar/issues/1830/pledge.svg">
</picture>
</a>
<!-- POLAR PLEDGE BADGE END -->



Discussion:
This seems to be a regression. @Goldziher?
I'll handle it this weekend 
It turns out this is not completely fixed (or I hit a similar bug).

MCVE:
```py
from litestar import Litestar, Router, get


@get("/{name:str}")
async def name_greeting(name: str) -> str:
    return f"Hello, {name}!"


@get("/{age:int}")
async def age_greeting(name: str, age: int) -> str:
    return f"Hello, {name}! {age} is a great age to be!"


app = Litestar(
    [
        Router(
            "/name",
            route_handlers=[
                name_greeting,
                Router("/{name:str}/age", route_handlers=[age_greeting]),
            ],
        )
    ]
)
```
----

```
✅  curl http://localhost:8508/name/jon
Hello, jon!

✅ curl http://localhost:8508/name/jon/age/42
Hello, jon! 42 is a great age to be!

❌  curl http://localhost:8508/name/jon/some-bogus-path
Hello, jon!
```
can you take this one on @gsakkis ? the fix should be in `traversal.py`

Resolving patch:
diff --git a/litestar/_asgi/routing_trie/traversal.py b/litestar/_asgi/routing_trie/traversal.py
--- a/litestar/_asgi/routing_trie/traversal.py
+++ b/litestar/_asgi/routing_trie/traversal.py
@@ -51,8 +51,7 @@ def traverse_route_map(
             path_params.append(component)
             continue
 
-        if i != len(path_components) - 1 or not current_node.children:
-            raise NotFoundException()
+        raise NotFoundException()
 
     if not current_node.asgi_handlers:
         raise NotFoundException()


Test patch:
diff --git a/tests/e2e/test_routing/test_path_resolution.py b/tests/e2e/test_routing/test_path_resolution.py
--- a/tests/e2e/test_routing/test_path_resolution.py
+++ b/tests/e2e/test_routing/test_path_resolution.py
@@ -3,7 +3,7 @@
 
 import pytest
 
-from litestar import Controller, MediaType, delete, get, post
+from litestar import Controller, MediaType, Router, delete, get, post
 from litestar.contrib.pydantic import _model_dump
 from litestar.status_codes import (
     HTTP_200_OK,
@@ -274,3 +274,29 @@ async def hello_world(name: str) -> str:
 
         response = client.get("/jon/bon/jovi")
         assert response.status_code == HTTP_404_NOT_FOUND
+
+
+def test_root_path_param_resolution_2() -> None:
+    # https://github.com/litestar-org/litestar/issues/1830#issuecomment-1642291149
+    @get("/{name:str}")
+    async def name_greeting(name: str) -> str:
+        return f"Hello, {name}!"
+
+    @get("/{age:int}")
+    async def age_greeting(name: str, age: int) -> str:
+        return f"Hello, {name}! {age} is a great age to be!"
+
+    age_router = Router("/{name:str}/age", route_handlers=[age_greeting])
+    name_router = Router("/name", route_handlers=[name_greeting, age_router])
+
+    with create_test_client(name_router) as client:
+        response = client.get("/name/jon")
+        assert response.status_code == HTTP_200_OK
+        assert response.text == "Hello, jon!"
+
+        response = client.get("/name/jon/age/42")
+        assert response.status_code == HTTP_200_OK
+        assert response.text == "Hello, jon! 42 is a great age to be!"
+
+        response = client.get("/name/jon/bon")
+        assert response.status_code == HTTP_404_NOT_FOUND