starlette/docs/websockets.md

126 lines
3.6 KiB
Markdown
Raw Normal View History

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)`
```python
from starlette.websockets import WebSocket
async def app(scope, receive, send):
2019-06-10 08:18:08 +00:00
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.
```python hl_lines="7-8"
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()`
Support the WebSocket Denial Response ASGI extension (#2041) * supply asgi_extensions to TestClient * Add WebSocket.send_response() * Add response support for WebSocket testclient * fix test for filesystem line-endings * lintint * support websocket.http.response extension by default * Improve coverate * Apply suggestions from code review Co-authored-by: Marcelo Trylesinski <marcelotryle@gmail.com> * Undo unrelated change * fix incorrect error message * Update starlette/websockets.py Co-authored-by: Marcelo Trylesinski <marcelotryle@gmail.com> * formatting * Re-introduce close-code and close-reason to WebSocketReject * Make sure the "websocket.connect" message is received in tests * Deliver a websocket.disconnect message to the app even if it closes/rejects itself. * Add test for filling out missing `websocket.disconnect` code * Add rejection headers. Expand tests. * Fix types, headers in message are `bytes` tuples. * Minimal WebSocket Denial Response implementation * Revert "Minimal WebSocket Denial Response implementation" This reverts commit 7af10ddcfa5423c18953cf5d1317cb5aa30a014c. * Rename to send_denial_response and update documentation * Remove the app_disconnect_msg. This can be added later in a separate PR * Remove status code 1005 from this PR * Assume that the application has tested for the extension before sending websocket.http.response.start * Rename WebSocketReject to WebSocketDenialResponse * Remove code and status from WebSocketDenialResponse. Just send a regular WebSocketDisconnect even when connection is rejected with close() * Raise an exception if attempting to send a http response and server does not support it. * WebSocketDenialClose and WebSocketDenialResponse These are both instances of WebSocketDenial. * Update starlette/testclient.py Co-authored-by: Marcelo Trylesinski <marcelotryle@gmail.com> * Revert "WebSocketDenialClose and WebSocketDenialResponse" This reverts commit 71b76e3f1c87064fe8458ff9d4ad0b242cbf15e7. * Rename parameters, member variables * Use httpx.Response as the base for WebSocketDenialResponse. * Apply suggestions from code review Co-authored-by: Marcelo Trylesinski <marcelotryle@gmail.com> * Update sanity check message * Remove un-needed function * Expand error message test regex * Add type hings to test methods * Add doc string to test. * Fix mypy complaining about mismatching parent methods. * nitpick & remove test * Simplify the documentation * Update starlette/testclient.py * Update starlette/testclient.py * Remove an unnecessary test * there is no special "close because of rejection" in the testclient anymore. --------- Co-authored-by: Marcelo Trylesinski <marcelotryle@gmail.com>
2024-02-04 20:16:10 +00:00
### 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.