Open fernhaven opened 3 months ago
I faced the same problem. I'm trying to resolve uuid
and int
as path parameter, but in all cases only the first declared function will be called.
I managed to reproduce this issue with the following unit test. I am currently attempting understanding the issue, and hopefully I will come up with a fix
from litestar import get
from litestar.testing.helpers import create_test_client
def test_conflicting_handlers() -> None:
@get("/{id:int}")
async def hello_world_int(id: int) -> str:
return f"Hello, world (int)! {id}"
@get("/{id:str}")
async def hello_world_str(id: str) -> str:
return f"Hello, world (str)! {id}"
with create_test_client(route_handlers=[hello_world_int, hello_world_str]) as client:
response = client.get("/42")
assert response.status_code == 200
assert "int" in response.text # FAILED
response = client.get("/ABC")
assert response.status_code == 200
assert "str" in response.text
Hi @provinzkraut @Goldziher I need your guidance to come up with a solution. Please guide me towards someone else if you are not the right people to speak to. Also please guide me to the forum where we should have this discussion.
The problem here is that the RouteTrieNode
add_route_to_trie
doesn't differentiate between types of path parameters. When one is encountered it adds a PathParameterSentinel
that can only be unique per parent node.
# this is the line that checks if a PathParameterSentinel is already in the children of the parent.
# on the second route it is already there and a new node is not created
if next_node_key not in current_node.
current_node.children[next_node_key] = create_node(path_template=route.path_format)
Now that I understand the problem there are 2 solutions:
Introduce support for multiple path parameters differentiated by type.
Introduce validations for routes overriding eachother (the won't fix)
My vote is against introducing this new feature, and instead work on proper validations. With my understanding of the vision of Litestar is that parsing and validation parameters should be encoded at the level of the handler's function signature. You shouldn't have to have 2 routes for 2 different handlers. I think that for this case we should have some sort of union parameter, like this
@get("/{id}")
async def hello_world(id: int | str) -> str:
return f"Hello, world! {id}"
app = Litestar([hello_world])
Thanks for the investigation here @IvanovCosmin!
My vote is against introducing this new feature, and instead work on proper validations.
I agree. That seems to be the proper way to handle this.
Description
Was told Litestar is intended to route differently based on the type of the path parameter:
However, when providing route handlers in the order of
int path param handler
followed bystr path param handler
, thestr path param handler
is the only one that is called in the example code below.URL to code causing the issue
No response
MCVE
Steps to reproduce
Screenshots
No response
Logs
No response
Litestar Version
2.9.1
Platform