ASGI websockets behavior websocket.connect and websocket.accept #17
-
Just testing the websockets ASGI protocol behavior, in uvicorn and others, the following code i used async def app(scope, receive, send):
# handle non websocket
if scope['type'] == 'http':
await send({
'type': 'http.response.start',
'status': 200,
'headers': [
[b'content-type', b'text/plain'],
],
})
await send({
'type': 'http.response.body',
'body': b'Connect via ws protocol!',
})
if scope['type'] != 'websocket':
return
protocols = scope.get('subprotocols', [])
scope = await receive()
# get connection
assert scope['type'] == 'websocket.connect'
# accept connection
await send({
'type': 'websocket.accept',
'subprotocol': protocols[0] if len(protocols) > 0 else None
})
# get data
while True:
scope = await receive()
type = scope['type']
# disconnected!
if type == 'websocket.disconnect':
print("disconnected!", scope)
break
# echo!
await send({
'type': 'websocket.send',
'bytes': scope.get('bytes', None),
'text': scope.get('text', '')
}) The order: In granian ASGI: async def app(scope, receive, send):
# handle non websocket
if scope['type'] == 'http':
await send({
'type': 'http.response.start',
'status': 200,
'headers': [
[b'content-type', b'text/plain'],
],
})
await send({
'type': 'http.response.body',
'body': b'Connect via ws protocol!',
})
if scope['type'] != 'websocket':
return
protocols = scope.get('subprotocols', [])
# accept connection
await send({
'type': 'websocket.accept',
'subprotocol': protocols[0] if len(protocols) > 0 else None
})
scope = await receive()
assert scope['type'] == 'websocket.connect'
# get data
while True:
scope = await receive()
type = scope['type']
# disconnected!
if type == 'websocket.disconnect':
print("disconnected!", scope)
break
# echo!
await send({
'type': 'websocket.send',
'bytes': scope.get('bytes', None),
'text': scope.get('text', '')
}) The order: Falcon source code for ASGI for reference: async def _handle_websocket(self, ver, scope, receive, send):
first_event = await receive()
if first_event['type'] != EventType.WS_CONNECT:
# NOTE(kgriffs): The handshake was abandoned or this is a message
# we don't support, so bail out. This also fulfills the ASGI
# spec requirement to only process the request after
# receiving and verifying the first event.
await send({'type': EventType.WS_CLOSE, 'code': WSCloseCode.SERVER_ERROR})
return https://github.com/falconry/falcon/blob/master/falcon/asgi/app.py Line 970 ASGI spec about websocket.connect
Another thing is if i call in granian await send({
'type': 'websocket.send',
'bytes': None,
'text': 'something'
}) It will send an empty binary message instead of using the 'text', in uvicorn the 'text' is sent if bytes is None
|
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 5 replies
-
Just opening the discussion before opening any Issue as an draft, Loving your work with Granian, i just implemented ASGI protocol wrapper for socketify.py, and i was testing against granian, uvicorn and using Falcon as Web Framework and found this out of spec things. Also wanna ask for an WebSocket sample of RSGI to test, thanks! |
Beta Was this translation helpful? Give feedback.
This is now tracked in #19 and #20