Los WebSockets son rutas, registradas igual que los handlers HTTP.
app_ws(pattern, handler) usa el mismo matcher
{param} — así que una sala de chat es solo un parámetro.
import "std/websocket" fn ws_room_handler(info: Array) -> int { let fd: int = info[0] let headers: Array = info[2] let params: Array = info[3] // plano [k1, v1, k2, v2, ...] var room: String = "?" var i: int = 0 while i + 1 < params.length() { let k: String = params[i] if k == "room" { let v: String = params[i + 1] room = v } i = i + 2 } let key: String = http_find_header(headers, "Sec-WebSocket-Key") tcp_write(fd, ws_handshake_response(key)) let data: String = tcp_read_partial(fd, 4096) if data.length() > 0 and !ws_is_close(data) { let msg: String = ws_parse(data) tcp_write(fd, ws_frame("[" + room + "] " + msg)) } tcp_write(fd, ws_close()) tcp_close(fd) return 1 // el fd es nuestro — el servidor no lo toca } fn main() { let app: App = app_new() app_ws("/ws/chat/{room}", ws_room_handler) serve_app(app, 3000, 8) }
El contrato del handler:
[fd, path, headers_flat, params_flat] — el socket crudo, el path, los headers del request, y los {params} que matchearon como array plano.1 para adueñarte: haces el handshake con ws_handshake_response, lees frames con ws_parse, escribes con ws_frame, y cierras tú. El servidor no vuelve a tocar el fd.0 para declinar y dejar pasar el request.Conéctate con cualquier cliente WebSocket a ws://localhost:3000/ws/chat/general y envía un mensaje — recibes de vuelta [general] tu mensaje. El parámetro {room} prueba que ruteó.
std/websocket.