websocket routes in blueprints

This commit is contained in:
Miguel Grinberg 2017-02-20 22:41:53 -08:00
parent 3bf79898d9
commit f90288f5dc
2 changed files with 48 additions and 0 deletions

View File

@ -23,6 +23,7 @@ class Blueprint:
self.host = host self.host = host
self.routes = [] self.routes = []
self.websocket_routes = []
self.exceptions = [] self.exceptions = []
self.listeners = defaultdict(list) self.listeners = defaultdict(list)
self.middlewares = [] self.middlewares = []
@ -46,6 +47,17 @@ class Blueprint:
host=future.host or self.host host=future.host or self.host
)(future.handler) )(future.handler)
for future in self.websocket_routes:
# attach the blueprint name to the handler so that it can be
# prefixed properly in the router
future.handler.__blueprintname__ = self.name
# Prepend the blueprint URI prefix if available
uri = url_prefix + future.uri if url_prefix else future.uri
app.websocket(
uri=uri,
host=future.host or self.host
)(future.handler)
# Middleware # Middleware
for future in self.middlewares: for future in self.middlewares:
if future.args or future.kwargs: if future.args or future.kwargs:
@ -106,6 +118,28 @@ class Blueprint:
self.route(uri=uri, methods=methods, host=host)(handler) self.route(uri=uri, methods=methods, host=host)(handler)
return handler return handler
def websocket(self, uri, host=None):
"""Create a blueprint websocket route from a decorated function.
:param uri: endpoint at which the route will be accessible.
"""
def decorator(handler):
route = FutureRoute(handler, uri, [], host)
self.websocket_routes.append(route)
return handler
return decorator
def add_websocket_route(self, handler, uri, host=None):
"""Create a blueprint websocket route from a function.
:param handler: function for handling uri requests. Accepts function,
or class instance with a view_class method.
:param uri: endpoint at which the route will be accessible.
:return: function or class instance
"""
self.websocket(uri=uri, host=host)(handler)
return handler
def listener(self, event): def listener(self, event):
"""Create a listener from a decorated function. """Create a listener from a decorated function.

View File

@ -1,3 +1,4 @@
import asyncio
import inspect import inspect
from sanic import Sanic from sanic import Sanic
@ -236,6 +237,7 @@ def test_bp_static():
def test_bp_shorthand(): def test_bp_shorthand():
app = Sanic('test_shorhand_routes') app = Sanic('test_shorhand_routes')
blueprint = Blueprint('test_shorhand_routes') blueprint = Blueprint('test_shorhand_routes')
ev = asyncio.Event()
@blueprint.get('/get') @blueprint.get('/get')
def handler(request): def handler(request):
@ -265,6 +267,10 @@ def test_bp_shorthand():
def handler(request): def handler(request):
return text('OK') return text('OK')
@blueprint.websocket('/ws')
async def handler(request, ws):
ev.set()
app.blueprint(blueprint) app.blueprint(blueprint)
request, response = app.test_client.get('/get') request, response = app.test_client.get('/get')
@ -308,3 +314,11 @@ def test_bp_shorthand():
request, response = app.test_client.get('/delete') request, response = app.test_client.get('/delete')
assert response.status == 405 assert response.status == 405
request, response = app.test_client.get('/ws', headers={
'Upgrade': 'websocket',
'Connection': 'upgrade',
'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==',
'Sec-WebSocket-Version': '13'})
assert response.status == 101
assert ev.is_set()