Allow route decorators to stack up again (#1764)
* Allow route decorators to stack up without causing a function signature inspection crash Fix #1742 * Apply fix to @websocket routes docorator too Add test for double-stacked websocket decorator remove introduction of new variable in route wrapper, extend routes in-place. Add explanation of why a handler will be a tuple in the case of a double-stacked route decorator
This commit is contained in:
parent
caa1b4d69b
commit
b565072ed9
21
sanic/app.py
21
sanic/app.py
|
@ -194,6 +194,12 @@ class Sanic:
|
|||
strict_slashes = self.strict_slashes
|
||||
|
||||
def response(handler):
|
||||
if isinstance(handler, tuple):
|
||||
# if a handler fn is already wrapped in a route, the handler
|
||||
# variable will be a tuple of (existing routes, handler fn)
|
||||
routes, handler = handler
|
||||
else:
|
||||
routes = []
|
||||
args = list(signature(handler).parameters.keys())
|
||||
|
||||
if not args:
|
||||
|
@ -205,7 +211,8 @@ class Sanic:
|
|||
if stream:
|
||||
handler.is_stream = stream
|
||||
|
||||
routes = self.router.add(
|
||||
routes.extend(
|
||||
self.router.add(
|
||||
uri=uri,
|
||||
methods=methods,
|
||||
handler=handler,
|
||||
|
@ -214,6 +221,7 @@ class Sanic:
|
|||
version=version,
|
||||
name=name,
|
||||
)
|
||||
)
|
||||
return routes, handler
|
||||
|
||||
return response
|
||||
|
@ -476,6 +484,13 @@ class Sanic:
|
|||
strict_slashes = self.strict_slashes
|
||||
|
||||
def response(handler):
|
||||
if isinstance(handler, tuple):
|
||||
# if a handler fn is already wrapped in a route, the handler
|
||||
# variable will be a tuple of (existing routes, handler fn)
|
||||
routes, handler = handler
|
||||
else:
|
||||
routes = []
|
||||
|
||||
async def websocket_handler(request, *args, **kwargs):
|
||||
request.app = self
|
||||
if not getattr(handler, "__blueprintname__", False):
|
||||
|
@ -516,7 +531,8 @@ class Sanic:
|
|||
self.websocket_tasks.remove(fut)
|
||||
await ws.close()
|
||||
|
||||
routes = self.router.add(
|
||||
routes.extend(
|
||||
self.router.add(
|
||||
uri=uri,
|
||||
handler=websocket_handler,
|
||||
methods=frozenset({"GET"}),
|
||||
|
@ -524,6 +540,7 @@ class Sanic:
|
|||
strict_slashes=strict_slashes,
|
||||
name=name,
|
||||
)
|
||||
)
|
||||
return routes, handler
|
||||
|
||||
return response
|
||||
|
|
|
@ -551,6 +551,35 @@ def test_route_duplicate(app):
|
|||
pass
|
||||
|
||||
|
||||
def test_double_stack_route(app):
|
||||
@app.route("/test/1")
|
||||
@app.route("/test/2")
|
||||
async def handler1(request):
|
||||
return text("OK")
|
||||
|
||||
request, response = app.test_client.get("/test/1")
|
||||
assert response.status == 200
|
||||
request, response = app.test_client.get("/test/2")
|
||||
assert response.status == 200
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_websocket_route_asgi(app):
|
||||
ev = asyncio.Event()
|
||||
|
||||
@app.websocket("/test/1")
|
||||
@app.websocket("/test/2")
|
||||
async def handler(request, ws):
|
||||
ev.set()
|
||||
|
||||
request, response = await app.asgi_client.websocket("/test/1")
|
||||
first_set = ev.is_set()
|
||||
ev.clear()
|
||||
request, response = await app.asgi_client.websocket("/test/1")
|
||||
second_set = ev.is_set()
|
||||
assert(first_set and second_set)
|
||||
|
||||
|
||||
def test_method_not_allowed(app):
|
||||
@app.route("/test", methods=["GET"])
|
||||
async def handler(request):
|
||||
|
|
Loading…
Reference in New Issue
Block a user