accept strict_slash routes

This commit is contained in:
Raphael Deem 2017-03-15 21:11:45 -07:00
parent fa69892f70
commit 46677e69ce
3 changed files with 65 additions and 23 deletions

View File

@ -101,7 +101,8 @@ class Sanic:
return decorator return decorator
# Decorator # Decorator
def route(self, uri, methods=frozenset({'GET'}), host=None): def route(self, uri, methods=frozenset({'GET'}), host=None,
strict_slashes=False):
"""Decorate a function to be registered as a route """Decorate a function to be registered as a route
:param uri: path of the URL :param uri: path of the URL
@ -117,34 +118,42 @@ class Sanic:
def response(handler): def response(handler):
self.router.add(uri=uri, methods=methods, handler=handler, self.router.add(uri=uri, methods=methods, handler=handler,
host=host) host=host, strict_slashes=strict_slashes)
return handler return handler
return response return response
# Shorthand method decorators # Shorthand method decorators
def get(self, uri, host=None): def get(self, uri, host=None, strict_slashes=False):
return self.route(uri, methods=frozenset({"GET"}), host=host) return self.route(uri, methods=frozenset({"GET"}), host=host,
strict_slashes=strict_slashes)
def post(self, uri, host=None): def post(self, uri, host=None, strict_slashes=False):
return self.route(uri, methods=frozenset({"POST"}), host=host) return self.route(uri, methods=frozenset({"POST"}), host=host,
strict_slashes=strict_slashes)
def put(self, uri, host=None): def put(self, uri, host=None, strict_slashes=False):
return self.route(uri, methods=frozenset({"PUT"}), host=host) return self.route(uri, methods=frozenset({"PUT"}), host=host,
strict_slashes=strict_slashes)
def head(self, uri, host=None): def head(self, uri, host=None, strict_slashes=False):
return self.route(uri, methods=frozenset({"HEAD"}), host=host) return self.route(uri, methods=frozenset({"HEAD"}), host=host,
strict_slashes=strict_slashes)
def options(self, uri, host=None): def options(self, uri, host=None, strict_slashes=False):
return self.route(uri, methods=frozenset({"OPTIONS"}), host=host) return self.route(uri, methods=frozenset({"OPTIONS"}), host=host,
strict_slashes=strict_slashes)
def patch(self, uri, host=None): def patch(self, uri, host=None, strict_slashes=False):
return self.route(uri, methods=frozenset({"PATCH"}), host=host) return self.route(uri, methods=frozenset({"PATCH"}), host=host,
strict_slashes=strict_slashes)
def delete(self, uri, host=None): def delete(self, uri, host=None, strict_slashes=False):
return self.route(uri, methods=frozenset({"DELETE"}), host=host) return self.route(uri, methods=frozenset({"DELETE"}), host=host,
strict_slashes=strict_slashes)
def add_route(self, handler, uri, methods=frozenset({'GET'}), host=None): def add_route(self, handler, uri, methods=frozenset({'GET'}), host=None,
strict_slashes=False):
"""A helper method to register class instance or """A helper method to register class instance or
functions as a handler to the application url functions as a handler to the application url
routes. routes.
@ -168,11 +177,12 @@ class Sanic:
if isinstance(handler, CompositionView): if isinstance(handler, CompositionView):
methods = handler.handlers.keys() methods = handler.handlers.keys()
self.route(uri=uri, methods=methods, host=host)(handler) self.route(uri=uri, methods=methods, host=host,
strict_slashes=strict_slashes)(handler)
return handler return handler
# Decorator # Decorator
def websocket(self, uri, host=None): def websocket(self, uri, host=None, strict_slashes=False):
"""Decorate a function to be registered as a websocket route """Decorate a function to be registered as a websocket route
:param uri: path of the URL :param uri: path of the URL
:param host: :param host:
@ -198,14 +208,17 @@ class Sanic:
await ws.close() await ws.close()
self.router.add(uri=uri, handler=websocket_handler, self.router.add(uri=uri, handler=websocket_handler,
methods=frozenset({'GET'}), host=host) methods=frozenset({'GET'}), host=host,
strict_slashes=strict_slashes)
return handler return handler
return response return response
def add_websocket_route(self, handler, uri, host=None): def add_websocket_route(self, handler, uri, host=None,
strict_slashes=False):
"""A helper method to register a function as a websocket route.""" """A helper method to register a function as a websocket route."""
return self.websocket(uri, host=host)(handler) return self.websocket(uri, host=host,
strict_slashes=strict_slashes)(handler)
def enable_websocket(self, enable=True): def enable_websocket(self, enable=True):
"""Enable or disable the support for websocket. """Enable or disable the support for websocket.

View File

@ -95,9 +95,15 @@ class Router:
return name, _type, pattern return name, _type, pattern
def add(self, uri, methods, handler, host=None): def add(self, uri, methods, handler, host=None, strict_slashes=False):
# add regular version # add regular version
self._add(uri, methods, handler, host) self._add(uri, methods, handler, host)
if strict_slashes:
return
# Add versions with and without trailing /
slash_is_missing = ( slash_is_missing = (
not uri[-1] == '/' not uri[-1] == '/'
and not self.routes_all.get(uri + '/', False) and not self.routes_all.get(uri + '/', False)

View File

@ -23,6 +23,29 @@ def test_shorthand_routes_get():
request, response = app.test_client.post('/get') request, response = app.test_client.post('/get')
assert response.status == 405 assert response.status == 405
def test_route_strict_slash():
app = Sanic('test_route_strict_slash')
@app.get('/get', strict_slashes=True)
def handler(request):
return text('OK')
@app.post('/post/', strict_slashes=True)
def handler(request):
return text('OK')
request, response = app.test_client.get('/get')
assert response.text == 'OK'
request, response = app.test_client.get('/get/')
assert response.status == 404
request, response = app.test_client.post('/post/')
assert response.text == 'OK'
request, response = app.test_client.post('/post')
assert response.status == 404
def test_route_optional_slash(): def test_route_optional_slash():
app = Sanic('test_route_optional_slash') app = Sanic('test_route_optional_slash')