- kaya-core: WebSocket ABC gains session attribute and accept(headers=...) - kaya-core: AsgiWebSocket injects headers into websocket.accept message - kaya-rsgi: RsgiWebSocket accepts headers param (ignored — Granian's accept() takes no args) - kaya-session: SessionWebSocket wrapper exposes ws.session and injects Set-Cookie on accept() - kaya-session: SessionMixin registers before/after websocket hooks; session loaded at connect, persisted on close if modified - 10 new WV session tests covering read, persist, handshake cookie, regenerate, invalidate, isolation - Example and README updated
42 lines
1.2 KiB
Python
42 lines
1.2 KiB
Python
from kaya.core import HttpContext, KayaApp, WebSocket
|
|
from kaya.session import InMemorySessionStore, SessionMixin
|
|
|
|
app = KayaApp(mixins=[SessionMixin(InMemorySessionStore())])
|
|
|
|
|
|
@app.GET('/')
|
|
async def home(ctx: HttpContext) -> None:
|
|
visits = ctx.session.get('visits', 0) + 1
|
|
ctx.session['visits'] = visits
|
|
await ctx.send_str(200, f'visits: {visits}')
|
|
|
|
|
|
@app.GET('/read')
|
|
async def read(ctx: HttpContext) -> None:
|
|
visits = ctx.session.get('visits', 0)
|
|
await ctx.send_str(200, f'visits: {visits}')
|
|
|
|
|
|
@app.GET('/clear')
|
|
async def clear(ctx: HttpContext) -> None:
|
|
ctx.session.invalidate()
|
|
await ctx.send_str(200, 'session cleared')
|
|
|
|
@app.websocket('/echo')
|
|
async def echo(ws: WebSocket) -> None:
|
|
await ws.accept()
|
|
async for msg in ws:
|
|
if msg.kind == 'text':
|
|
await ws.send_text(f"echo: {msg.data}")
|
|
elif msg.kind == 'binary':
|
|
data = msg.data
|
|
assert isinstance(data, bytes)
|
|
await ws.send_bytes(data)
|
|
|
|
@app.websocket('/ws/visits')
|
|
async def ws_visits(ws: WebSocket) -> None:
|
|
visits = ws.session.get('visits', 0) + 1
|
|
ws.session['visits'] = visits
|
|
await ws.accept()
|
|
await ws.send_text(f'visits: {visits}')
|