[WIP] Handle scope["root_path"] and scope["path"] as per ASGI spec
- [X] Initially raised as issue #1336
Rationale
This is an exploratory work as how to solve issue #1336. The issue details the problem quite well but in a nutshell:
- The issue arises when using a
Mountrouter alongside theroot_pathoption. - We consider that
pathis the remainder of the whole path striped fromroot_path. As pointed out here, this is not how the ASGI spec was imagined:pathshould containroot_path. - As a consequence, every route matching is done assuming the `root_path* is not present in the path.
- Besides, we use this behavior to recursively handle
Mountrouters, by adding the router prefix onroot_pathand strippingpathuntil we match the single route:
https://github.com/encode/starlette/blob/e3de71f1433568a3f7ac3dc69ef86cf4f72f5651/starlette/routing.py#L378-L390
Notice that we define an app_root_path to keep track of the original root_path.
The way I understand it, we should keep both path and root_path untouched. It's a shame of course because we won't be able to handle Mount elegantly as we do now.
Current work status
First of all, I added a unit test to reproduce the issue.
Then, I've tried a first approach to solve it which consists of two things:
- Instead of using
pathandroot_pathdirectly, use internal variablescurrent_pathandcurrent_root_path(admittedly, this is a very uninspired naming) to allow our recursive approach - Take care of stripping the
root_pathfrom thepathso we can match properly, both inRouteandMount
This solves the specific problem but breaks other parts of the code. Obviously, every parts of the routing which makes use of the path will need to account for this root_path, e.g. in WebSocketRoute or in Router, in the part where we make slash redirects.
An idea I had to tackle this would be to have a common prepare_scope which could be called by the Route classes to prepare the path, add the "internal" variables, while keeping the original path and root_path untouched.
Before going further, I would be interested in your views and opinions about this so we can take the right path.
Cheers!