WebSockets
Starlette includes a WebSocket
class that fulfils a similar role
to the HTTP request, but that allows sending and receiving data on a websocket.
WebSocket
Signature: WebSocket(scope, receive=None, send=None)
from starlette.websockets import WebSocket
async def app(scope, receive, send):
websocket = WebSocket(scope=scope, receive=receive, send=send)
await websocket.accept()
await websocket.send_text('Hello, world!')
await websocket.close()
WebSockets present a mapping interface, so you can use them in the same
way as a scope
.
For instance: websocket['path']
will return the ASGI path.
URL
The websocket URL is accessed as websocket.url
.
The property is actually a subclass of str
, and also exposes all the
components that can be parsed out of the URL.
For example: websocket.url.path
, websocket.url.port
, websocket.url.scheme
.
Headers
Headers are exposed as an immutable, case-insensitive, multi-dict.
For example: websocket.headers['sec-websocket-version']
Query Parameters
Query parameters are exposed as an immutable multi-dict.
For example: websocket.query_params['search']
Path Parameters
Router path parameters are exposed as a dictionary interface.
For example: websocket.path_params['username']
Accepting the connection
await websocket.accept(subprotocol=None, headers=None)
Sending data
await websocket.send_text(data)
await websocket.send_bytes(data)
await websocket.send_json(data)
JSON messages default to being sent over text data frames, from version 0.10.0 onwards.
Use websocket.send_json(data, mode="binary")
to send JSON over binary data frames.
Receiving data
await websocket.receive_text()
await websocket.receive_bytes()
await websocket.receive_json()
May raise starlette.websockets.WebSocketDisconnect()
.
JSON messages default to being received over text data frames, from version 0.10.0 onwards.
Use websocket.receive_json(data, mode="binary")
to receive JSON over binary data frames.
Iterating data
websocket.iter_text()
websocket.iter_bytes()
websocket.iter_json()
Similar to receive_text
, receive_bytes
, and receive_json
but returns an
async iterator.
from starlette.websockets import WebSocket
async def app(scope, receive, send):
websocket = WebSocket(scope=scope, receive=receive, send=send)
await websocket.accept()
async for message in websocket.iter_text():
await websocket.send_text(f"Message text was: {message}")
await websocket.close()
When starlette.websockets.WebSocketDisconnect
is raised, the iterator will exit.
Closing the connection
await websocket.close(code=1000, reason=None)
Sending and receiving messages
If you need to send or receive raw ASGI messages then you should use
websocket.send()
and websocket.receive()
rather than using the raw send
and
receive
callables. This will ensure that the websocket's state is kept
correctly updated.
await websocket.send(message)
await websocket.receive()
Send Denial Response
If you call websocket.close()
before calling websocket.accept()
then
the server will automatically send a HTTP 403 error to the client.
If you want to send a different error response, you can use the
websocket.send_denial_response()
method. This will send the response
and then close the connection.
await websocket.send_denial_response(response)
This requires the ASGI server to support the WebSocket Denial Response
extension. If it is not supported a RuntimeError
will be raised.