From 60774c5a49abc7397aca36d51d30a211b586cba1 Mon Sep 17 00:00:00 2001 From: Timothy Ebiuwhe Date: Fri, 9 Feb 2018 22:27:20 +0100 Subject: [PATCH 1/2] Fixed bug that occurs on calling @app.route or any of it's variants causes a route to be added twice. One without the slash, the other with the Setting strict_slashes to false when a route does not end with slashes slash. This is ok if the Router._add method runs linearly, but problematic when it runs recursively. Unfortunately recursion is triggered when the host param to the Router._add function is a list of hosts. --- sanic/router.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sanic/router.py b/sanic/router.py index 052ff1bf..8b3fd3dc 100644 --- a/sanic/router.py +++ b/sanic/router.py @@ -128,6 +128,13 @@ class Router: if strict_slashes: return + if not isinstance(host, str) and host is not None: + # we have gotten back to the top of the recursion tree where the + # host was originally a list. By now, we've processed the strict + # slashes logic on the leaf nodes (the individual host strings in + # the list of host) + return + # Add versions with and without trailing / slashed_methods = self.routes_all.get(uri + '/', frozenset({})) unslashed_methods = self.routes_all.get(uri[:-1], frozenset({})) From 220b40f7f443f1050cbf26c6bf7f2a58730470ff Mon Sep 17 00:00:00 2001 From: Timothy Ebiuwhe Date: Fri, 9 Feb 2018 22:33:34 +0100 Subject: [PATCH 2/2] Added regression tests for issue #1120 --- tests/test_routes.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/test_routes.py b/tests/test_routes.py index 5f3b3376..ed35ea48 100644 --- a/tests/test_routes.py +++ b/tests/test_routes.py @@ -174,6 +174,40 @@ def test_route_optional_slash(): request, response = app.test_client.get('/get/') assert response.text == 'OK' +def test_route_strict_slashes_set_to_false_and_host_is_a_list(): + #Part of regression test for issue #1120 + app = Sanic('test_route_strict_slashes_set_to_false_and_host_is_a_list') + + site1 = 'localhost:{}'.format(app.test_client.port) + + #before fix, this raises a RouteExists error + @app.get('/get', host=[site1, 'site2.com'], strict_slashes=False) + def handler(request): + return text('OK') + + request, response = app.test_client.get('http://' + site1 + '/get') + assert response.text == 'OK' + + @app.post('/post', host=[site1, 'site2.com'], strict_slashes=False) + def handler(request): + return text('OK') + + request, response = app.test_client.post('http://' + site1 +'/post') + assert response.text == 'OK' + + @app.put('/put', host=[site1, 'site2.com'], strict_slashes=False) + def handler(request): + return text('OK') + + request, response = app.test_client.put('http://' + site1 +'/put') + assert response.text == 'OK' + + @app.delete('/delete', host=[site1, 'site2.com'], strict_slashes=False) + def handler(request): + return text('OK') + + request, response = app.test_client.delete('http://' + site1 +'/delete') + assert response.text == 'OK' def test_shorthand_routes_post(): app = Sanic('test_shorhand_routes_post')