Skip to content

Commit

Permalink
Weboscket subprotocol negotiation
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelgrinberg committed Aug 8, 2017
1 parent 7b66a56 commit 8048b96
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 3 deletions.
7 changes: 5 additions & 2 deletions sanic/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,12 @@ def add_route(self, handler, uri, methods=frozenset({'GET'}), host=None,
return handler

# Decorator
def websocket(self, uri, host=None, strict_slashes=False):
def websocket(self, uri, subprotocols=None, host=None,
strict_slashes=False):
"""Decorate a function to be registered as a websocket route
:param uri: path of the URL
:param subprotocols: optional list of strings with the supported
subprotocols
:param host:
:return: decorated function
"""
Expand All @@ -236,7 +239,7 @@ async def websocket_handler(request, *args, **kwargs):
# On Python3.5 the Transport classes in asyncio do not
# have a get_protocol() method as in uvloop
protocol = request.transport._protocol
ws = await protocol.websocket_handshake(request)
ws = await protocol.websocket_handshake(request, subprotocols)

# schedule the application handler
# its future is kept in self.websocket_tasks in case it
Expand Down
14 changes: 13 additions & 1 deletion sanic/websocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def write_response(self, response):
else:
super().write_response(response)

async def websocket_handshake(self, request):
async def websocket_handshake(self, request, subprotocols=None):
# let the websockets package do the handshake with the client
headers = []

Expand All @@ -57,6 +57,17 @@ def set_header(k, v):
except InvalidHandshake:
raise InvalidUsage('Invalid websocket request')

subprotocol = None
if subprotocols and 'Sec-Websocket-Protocol' in request.headers:
# select a subprotocol
client_subprotocols = [p.strip() for p in request.headers[
'Sec-Websocket-Protocol'].split(',')]
for p in client_subprotocols:
if p in subprotocols:
subprotocol = p
set_header('Sec-Websocket-Protocol', subprotocol)
break

# write the 101 response back to the client
rv = b'HTTP/1.1 101 Switching Protocols\r\n'
for k, v in headers:
Expand All @@ -69,5 +80,6 @@ def set_header(k, v):
max_size=self.websocket_max_size,
max_queue=self.websocket_max_queue
)
self.websocket.subprotocol = subprotocol
self.websocket.connection_made(request.transport)
return self.websocket

0 comments on commit 8048b96

Please sign in to comment.