-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handlers with path variables are used even if parent route exists #2239
Comments
@samdbmg This is probably a bug in one of the recently done router changes. I am away from my dev machine and cannot try myself, but could you check if setting |
This is not a bug, at least not in the current version. If anything, it was a bug that existed prior to 21.3. When you define a route like this: @app.route('/foo/') Sanic will look at that and take off the trailing slash because it is ambiguous. Therefore, when it is matching a request, it is looking for something that has only one segment in the path: Now, when you happen to have another endpoint like this that is looking for a 2 segments: @app.route('/foo/<var>/') The game changes. On the first pass through, Sanic finds and endpoint that matches. When you hit the endpoint as If you really want @app.route("/foo/", strict_slashes=True)
async def test(request):
return json({"hello": "world"})
@app.route("/foo/<var>/")
async def myreq(request, var):
return json({"hello": var}) The problem with this is that you now will NOT match on:
To correct this: @app.route("/foo")
@app.route("/foo/", strict_slashes=True)
async def test(request):
return json({"hello": "world"})
Anytime that you start adding trailing slashes to a request, you need to be careful. There is an RFC that discusses this in greater detail if you are interested: https://datatracker.ietf.org/doc/html/rfc3986/#section-6 Also, there is the older: https://datatracker.ietf.org/doc/html/rfc2616#section-3.2.3 A trailing slash on a request is significant. It should be treated as such. Here is another explanation I gave that may be relevant/helpful: https://community.sanicframework.org/t/route-paths-how-do-they-work/825 Because this is intended and expected behavior, I am closing the issue. Please feel free to continue the conversation if this answer is not satisfactory. |
FWIW, there is also an alternative. And, this may or may not work for you depending upon what you expected By default, this: @app.route("/foo/<var>/") is interpreted as: @app.route("/foo/<var:str>/") If you change it to a different type (for example `alpha) @app.route("/foo/<var:alpha>/") Then, on the first pass through of matching |
Another example of why I personally don't ever expect web servers to do what the |
Brill, cheers for the detailed explanation, and clarifying that the old behaviour was the bug, rather than the new. I'd be inclined to agree with @Tronic that the manual should probably spend a few words on the implications of |
Describe the bug
Prior to Sanic 21, a route handler for
/foo/
would be used instead of one for/foo/<var>/
if a request was made forGET /foo/
, but now the second handler is called with an empty string for<var>
.Is this the intended behaviour - as in I should handle the case where the variable is empty instead of having a separate route? If so I'd have expected my example to throw a
sanic_routing.exceptions.RouteExists
to prevent me making this mistake.Code snippet
Expected behavior
Running the snippet above, I'd expect to see:
(which I what happens on sanic 20.12.3)
Instead I get (on 21.6.2 and also 21.3.0):
Environment (please complete the following information):
Apologies if this should be on sanic_routing - I don't really understand enough about the router to know!
The text was updated successfully, but these errors were encountered: