From 9c8a2a3f62ec5bf01ed2f138a9666821901fab56 Mon Sep 17 00:00:00 2001 From: Adam Hopkins Date: Mon, 22 Mar 2021 23:46:44 +0200 Subject: [PATCH 1/2] Make sure that blueprints with no slash is maintained when applied --- sanic/blueprints.py | 6 ++++- sanic/mixins/routes.py | 2 +- tests/test_routes.py | 58 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 63 insertions(+), 3 deletions(-) diff --git a/sanic/blueprints.py b/sanic/blueprints.py index 85b60ddc18..2d1e6a1d5e 100644 --- a/sanic/blueprints.py +++ b/sanic/blueprints.py @@ -85,7 +85,11 @@ def __init__( self.routes: List[Route] = [] self.statics: List[RouteHandler] = [] self.strict_slashes = strict_slashes - self.url_prefix = url_prefix + self.url_prefix = ( + url_prefix[:-1] + if url_prefix and url_prefix.endswith("/") + else url_prefix + ) self.version = version self.websocket_routes: List[Route] = [] diff --git a/sanic/mixins/routes.py b/sanic/mixins/routes.py index f57bf230be..27747ab3b4 100644 --- a/sanic/mixins/routes.py +++ b/sanic/mixins/routes.py @@ -71,7 +71,7 @@ def route( # Fix case where the user did not prefix the URL with a / # and will probably get confused as to why it's not working - if not uri.startswith("/"): + if not uri.startswith("/") and (uri or hasattr(self, "router")): uri = "/" + uri if strict_slashes is None: diff --git a/tests/test_routes.py b/tests/test_routes.py index 60c0e76054..a7f98fcf65 100644 --- a/tests/test_routes.py +++ b/tests/test_routes.py @@ -12,7 +12,7 @@ ) from sanic_testing.testing import SanicTestClient -from sanic import Blueprint, Sanic +from sanic import Blueprint, Sanic, response from sanic.constants import HTTP_METHODS from sanic.exceptions import NotFound, SanicException from sanic.request import Request @@ -1175,3 +1175,59 @@ async def handler(request): with pytest.raises(SanicException): app.router.finalize() + + +def test_routes_with_and_without_slash_definitions(app): + bar = Blueprint("bar", url_prefix="bar") + baz = Blueprint("baz", url_prefix="/baz") + fizz = Blueprint("fizz", url_prefix="fizz/") + buzz = Blueprint("buzz", url_prefix="/buzz/") + + instances = ( + (app, "foo"), + (bar, "bar"), + (baz, "baz"), + (fizz, "fizz"), + (buzz, "buzz"), + ) + + for instance, term in instances: + route = f"/{term}" if isinstance(instance, Sanic) else "" + + @instance.get(route, strict_slashes=True) + def get_without(request): + return text(f"{term}_without") + + @instance.get(f"{route}/", strict_slashes=True) + def get_with(request): + return text(f"{term}_with") + + @instance.post(route, strict_slashes=True) + def post_without(request): + return text(f"{term}_without") + + @instance.post(f"{route}/", strict_slashes=True) + def post_with(request): + return text(f"{term}_with") + + app.blueprint(bar) + app.blueprint(baz) + app.blueprint(fizz) + app.blueprint(buzz) + + for _, term in instances: + _, response = app.test_client.get(f"/{term}") + assert response.status == 200 + assert response.text == f"{term}_without" + + _, response = app.test_client.get(f"/{term}/") + assert response.status == 200 + assert response.text == f"{term}_with" + + _, response = app.test_client.post(f"/{term}") + assert response.status == 200 + assert response.text == f"{term}_without" + + _, response = app.test_client.post(f"/{term}/") + assert response.status == 200 + assert response.text == f"{term}_with" From 3fa76c0cfb2db9fe03bbbdae9baed64bbdafc5ea Mon Sep 17 00:00:00 2001 From: Adam Hopkins Date: Tue, 23 Mar 2021 01:18:39 +0200 Subject: [PATCH 2/2] Remove unneeded import --- tests/test_routes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_routes.py b/tests/test_routes.py index a7f98fcf65..4b2927ef14 100644 --- a/tests/test_routes.py +++ b/tests/test_routes.py @@ -12,7 +12,7 @@ ) from sanic_testing.testing import SanicTestClient -from sanic import Blueprint, Sanic, response +from sanic import Blueprint, Sanic from sanic.constants import HTTP_METHODS from sanic.exceptions import NotFound, SanicException from sanic.request import Request