Fix Daphne ASGI compatibility and document WS handshake cookie limitation

- AsgiContext and AsgiWebSocket now default missing  scope key
  to 'http' / 'ws' respectively (Daphne omits it for websocket scopes)
- Add regression test for websocket scope without scheme
- Update example/session.py WS handler to read the session; cookie must
  be set via HTTP first because common ASGI servers ignore the headers
  field on websocket.accept
- Update README with the same caveat about Granian/Daphne/curl
This commit is contained in:
2026-07-23 22:11:06 +08:00
parent e4e00762bb
commit ca023580e4
4 changed files with 39 additions and 12 deletions
+11 -8
View File
@@ -34,19 +34,22 @@ The same session is available in websocket handlers as `ws.session`:
```python
@app.websocket('/ws/visits')
async def ws_visits(ws: WebSocket):
visits = ws.session.get('visits', 0) + 1
ws.session['visits'] = visits
await ws.accept()
visits = ws.session.get('visits', 0)
await ws.send_text(f'visits: {visits}')
```
The session is loaded from the cookie when the connection is opened and
persisted when the connection closes, if it was modified. The session cookie
can only be set or refreshed on the handshake response, so mutate the session
*before* calling `ws.accept()` if you want the cookie delivered with the
handshake. Handshake cookies require ASGI spec version 2.1+; RSGI websocket
handshakes cannot carry response headers, so on RSGI the session is loaded and
persisted but the cookie is only set or refreshed by HTTP responses.
persisted when the connection closes, if it was modified.
**Important:** although the ASGI spec allows custom headers on the WebSocket
handshake response (`websocket.accept` headers, spec 2.1+), most ASGI servers
in practice — including **Granian** and **Daphne** — do not forward them into
the HTTP `101` response. RSGI websocket handshakes cannot carry response headers
at all. Therefore, in real deployments a session cookie can only be set or
refreshed by an HTTP response. Use an HTTP endpoint to establish or update the
session before opening the WebSocket, and read the existing session in the
WebSocket handler.
## Session expiry