WEBSOCKETS

Protect the upgrade before opening a socket

WebSockets can live in endpoint groups, inherit their path and middleware, and add route-specific middleware. Browser clients authenticate the upgrade with a search parameter because they cannot set arbitrary upgrade headers.

dowe
middleware requireSocketToken
  jwt verified secret:env.JWT_SECRET algorithm:"HS256" token:req.query.token
  if verified.valid
    next
  return response status:401 json:{ ok:false error:"Unauthorized" }

endpoints controlRoutes
  group path:"/api/v1/sip"
    websocket path:"/control" middleware:[requireSocketToken]
      open ws
        log "sip control websocket open"
      message ws
        let event = ws.json
        send ws json:{ ok:true channel:"sip-control" }
      close ws
        log "sip control websocket close"

Query values are credentials

Use short-lived tokens, serve only over TLS, and avoid logging complete WebSocket URLs. Dowe validates middleware before the upgrade is accepted.

Lifecycle remains explicit

open, message, close, and drain remain optional Rust-backed lifecycle handlers after authentication succeeds.