From 42cd42427437349ea0f3c4acf5acb9d21533e156 Mon Sep 17 00:00:00 2001 From: howie6879 Date: Sun, 7 Jan 2018 10:59:12 +0800 Subject: [PATCH 1/4] Fix: the Chinese URI --- sanic/app.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sanic/app.py b/sanic/app.py index 26ef83b0..7478c30a 100644 --- a/sanic/app.py +++ b/sanic/app.py @@ -7,7 +7,7 @@ from collections import deque, defaultdict from functools import partial from inspect import isawaitable, stack, getmodulename from traceback import format_exc -from urllib.parse import urlencode, urlunparse +from urllib.parse import quote, urlencode, urlunparse from ssl import create_default_context, Purpose from sanic.config import Config @@ -25,7 +25,6 @@ from sanic.websocket import WebSocketProtocol, ConnectionClosed class Sanic: - def __init__(self, name=None, router=None, error_handler=None, load_env=True, request_class=None, strict_slashes=False, log_config=None, @@ -111,9 +110,11 @@ class Sanic: :param event: event to listen to """ + def decorator(listener): self.listeners[event].append(listener) return listener + return decorator # Decorator @@ -135,7 +136,7 @@ class Sanic: # and will probably get confused as to why it's not working if not uri.startswith('/'): uri = '/' + uri - + uri = quote(uri) if stream: self.is_request_stream = True @@ -428,7 +429,7 @@ class Sanic: uri, route = self.router.find_route_by_view_name(view_name, **kw) if not (uri and route): raise URLBuildError('Endpoint with name `{}` was not found'.format( - view_name)) + view_name)) if view_name == 'static' or view_name.endswith('.static'): filename = kwargs.pop('filename', None) From e34de96b24f014704ea1e0a5623b90d2b05be798 Mon Sep 17 00:00:00 2001 From: howie6879 Date: Sun, 7 Jan 2018 12:06:21 +0800 Subject: [PATCH 2/4] Fix: the Chinese URI --- sanic/app.py | 9 ++++----- sanic/router.py | 2 ++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/sanic/app.py b/sanic/app.py index 7478c30a..26ef83b0 100644 --- a/sanic/app.py +++ b/sanic/app.py @@ -7,7 +7,7 @@ from collections import deque, defaultdict from functools import partial from inspect import isawaitable, stack, getmodulename from traceback import format_exc -from urllib.parse import quote, urlencode, urlunparse +from urllib.parse import urlencode, urlunparse from ssl import create_default_context, Purpose from sanic.config import Config @@ -25,6 +25,7 @@ from sanic.websocket import WebSocketProtocol, ConnectionClosed class Sanic: + def __init__(self, name=None, router=None, error_handler=None, load_env=True, request_class=None, strict_slashes=False, log_config=None, @@ -110,11 +111,9 @@ class Sanic: :param event: event to listen to """ - def decorator(listener): self.listeners[event].append(listener) return listener - return decorator # Decorator @@ -136,7 +135,7 @@ class Sanic: # and will probably get confused as to why it's not working if not uri.startswith('/'): uri = '/' + uri - uri = quote(uri) + if stream: self.is_request_stream = True @@ -429,7 +428,7 @@ class Sanic: uri, route = self.router.find_route_by_view_name(view_name, **kw) if not (uri and route): raise URLBuildError('Endpoint with name `{}` was not found'.format( - view_name)) + view_name)) if view_name == 'static' or view_name.endswith('.static'): filename = kwargs.pop('filename', None) diff --git a/sanic/router.py b/sanic/router.py index 0d8305ef..ad93fda7 100644 --- a/sanic/router.py +++ b/sanic/router.py @@ -2,6 +2,7 @@ import re from collections import defaultdict, namedtuple from collections.abc import Iterable from functools import lru_cache +from urllib.parse import unquote from sanic.exceptions import NotFound, MethodNotSupported from sanic.views import CompositionView @@ -373,6 +374,7 @@ class Router: :param method: request method :return: handler, arguments, keyword arguments """ + # url = unquote(url) url = host + url # Check against known static routes route = self.routes_static.get(url) From 7303a06f83eb7db54f7718d29b9e45369d3cac5f Mon Sep 17 00:00:00 2001 From: howie6879 Date: Sun, 7 Jan 2018 12:07:18 +0800 Subject: [PATCH 3/4] Fix: the Chinese URI --- sanic/router.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sanic/router.py b/sanic/router.py index ad93fda7..e399a6cf 100644 --- a/sanic/router.py +++ b/sanic/router.py @@ -374,7 +374,7 @@ class Router: :param method: request method :return: handler, arguments, keyword arguments """ - # url = unquote(url) + url = unquote(url) url = host + url # Check against known static routes route = self.routes_static.get(url) From 5f329f72ee99ab952f21dc163120d4f38633c254 Mon Sep 17 00:00:00 2001 From: howie6879 Date: Mon, 8 Jan 2018 08:38:54 +0800 Subject: [PATCH 4/4] Update test_routes.py --- sanic/router.py | 3 +-- tests/test_routes.py | 39 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/sanic/router.py b/sanic/router.py index e399a6cf..bd74c11d 100644 --- a/sanic/router.py +++ b/sanic/router.py @@ -374,8 +374,7 @@ class Router: :param method: request method :return: handler, arguments, keyword arguments """ - url = unquote(url) - url = host + url + url = unquote(host + url) # Check against known static routes route = self.routes_static.get(url) method_not_supported = MethodNotSupported( diff --git a/tests/test_routes.py b/tests/test_routes.py index fb47203f..84d6b221 100644 --- a/tests/test_routes.py +++ b/tests/test_routes.py @@ -29,7 +29,8 @@ def test_versioned_routes_get(method): client_method = getattr(app.test_client, method) request, response = client_method('/v1/{}'.format(method)) - assert response.status== 200 + assert response.status == 200 + def test_shorthand_routes_get(): app = Sanic('test_shorhand_routes_get') @@ -44,6 +45,7 @@ def test_shorthand_routes_get(): request, response = app.test_client.post('/get') assert response.status == 405 + def test_shorthand_routes_multiple(): app = Sanic('test_shorthand_routes_multiple') @@ -62,6 +64,7 @@ def test_shorthand_routes_multiple(): request, response = app.test_client.options('/get/') assert response.status == 200 + def test_route_strict_slash(): app = Sanic('test_route_strict_slash') @@ -89,6 +92,7 @@ def test_route_strict_slash(): request, response = app.test_client.post('/post') assert response.status == 404 + def test_route_invalid_parameter_syntax(): with pytest.raises(ValueError): app = Sanic('test_route_invalid_param_syntax') @@ -99,6 +103,7 @@ def test_route_invalid_parameter_syntax(): request, response = app.test_client.get('/get') + def test_route_strict_slash_default_value(): app = Sanic('test_route_strict_slash', strict_slashes=True) @@ -109,6 +114,7 @@ def test_route_strict_slash_default_value(): request, response = app.test_client.get('/get/') assert response.status == 404 + def test_route_strict_slash_without_passing_default_value(): app = Sanic('test_route_strict_slash') @@ -119,6 +125,7 @@ def test_route_strict_slash_without_passing_default_value(): request, response = app.test_client.get('/get/') assert response.text == 'OK' + def test_route_strict_slash_default_value_can_be_overwritten(): app = Sanic('test_route_strict_slash', strict_slashes=True) @@ -129,6 +136,7 @@ def test_route_strict_slash_default_value_can_be_overwritten(): request, response = app.test_client.get('/get/') assert response.text == 'OK' + def test_route_slashes_overload(): app = Sanic('test_route_slashes_overload') @@ -140,7 +148,6 @@ def test_route_slashes_overload(): def handler(request): return text('OK') - request, response = app.test_client.get('/hello') assert response.text == 'OK' @@ -153,6 +160,7 @@ def test_route_slashes_overload(): request, response = app.test_client.post('/hello/') assert response.text == 'OK' + def test_route_optional_slash(): app = Sanic('test_route_optional_slash') @@ -166,6 +174,7 @@ def test_route_optional_slash(): request, response = app.test_client.get('/get/') assert response.text == 'OK' + def test_shorthand_routes_post(): app = Sanic('test_shorhand_routes_post') @@ -179,6 +188,7 @@ def test_shorthand_routes_post(): request, response = app.test_client.get('/post') assert response.status == 405 + def test_shorthand_routes_put(): app = Sanic('test_shorhand_routes_put') @@ -195,6 +205,7 @@ def test_shorthand_routes_put(): request, response = app.test_client.get('/put') assert response.status == 405 + def test_shorthand_routes_delete(): app = Sanic('test_shorhand_routes_delete') @@ -211,6 +222,7 @@ def test_shorthand_routes_delete(): request, response = app.test_client.get('/delete') assert response.status == 405 + def test_shorthand_routes_patch(): app = Sanic('test_shorhand_routes_patch') @@ -227,6 +239,7 @@ def test_shorthand_routes_patch(): request, response = app.test_client.get('/patch') assert response.status == 405 + def test_shorthand_routes_head(): app = Sanic('test_shorhand_routes_head') @@ -243,6 +256,7 @@ def test_shorthand_routes_head(): request, response = app.test_client.get('/head') assert response.status == 405 + def test_shorthand_routes_options(): app = Sanic('test_shorhand_routes_options') @@ -259,6 +273,7 @@ def test_shorthand_routes_options(): request, response = app.test_client.get('/options') assert response.status == 405 + def test_static_routes(): app = Sanic('test_dynamic_route') @@ -741,6 +756,7 @@ def test_remove_inexistent_route(): with pytest.raises(RouteDoesNotExist): app.remove_route('/test') + def test_removing_slash(): app = Sanic(__name__) @@ -859,7 +875,6 @@ def test_unmergeable_overload_routes(): request, response = app.test_client.post('/overload_whole') assert response.text == 'OK1' - @app.route('/overload_part', methods=['GET']) async def handler1(request): return text('OK1') @@ -874,3 +889,21 @@ def test_unmergeable_overload_routes(): request, response = app.test_client.post('/overload_part') assert response.status == 405 + + +def test_unicode_routes(): + app = Sanic('test_unicode_routes') + + @app.get('/你好') + def handler1(request): + return text('OK1') + + request, response = app.test_client.get('/你好') + assert response.text == 'OK1' + + @app.route('/overload/', methods=['GET']) + async def handler2(request, param): + return text('OK2 ' + param) + + request, response = app.test_client.get('/overload/你好') + assert response.text == 'OK2 你好'