Appearance
WebSocket Session
WebSocket ingress handlers receive a session object that represents a single client connection. The session provides methods for sending messages, managing rooms, and storing per-connection state.
WebSocketSession
The session parameter is passed to onOpen(session), onMessage(session, message), and onClose(session).
session.id
The unique session ID (read-only).
- Type:
string
javascript
export function onOpen(session) {
console.log("Client connected:", session.id);
}session.send(message)
Send a text message to this client.
- Parameters:
message: string
javascript
session.send(JSON.stringify({ type: "welcome", id: session.id }));session.close()
Close the WebSocket connection.
javascript
if (shouldDisconnect) {
session.send(JSON.stringify({ type: "kicked", reason: "timeout" }));
session.close();
}session.isOpen()
Check if the connection is still open.
- Returns:
boolean
session.getParameter(name)
Get a query parameter from the WebSocket handshake URI.
- Parameters:
name: string - Returns:
string | null
javascript
// ws://host/ws/chat?room=general&user=alice
const room = session.getParameter("room"); // "general"
const user = session.getParameter("user"); // "alice"session.getHeader(name)
Get a header from the WebSocket handshake request.
- Parameters:
name: string - Returns:
string | null
javascript
const token = session.getHeader("Authorization");session.getRequestPath()
Get the URI path of the WebSocket connection.
- Returns:
string
session.getRemoteAddr()
Get the client's IP address.
- Returns:
string
session.setAttribute(key, value)
Store a custom attribute on this session. Useful for per-connection state like user identity.
- Parameters:
key: string,value: any
javascript
export function onOpen(session) {
const username = session.getParameter("user");
session.setAttribute("username", username);
}session.getAttribute(key)
Retrieve a custom attribute from this session.
- Parameters:
key: string - Returns:
any
javascript
export function onMessage(session, message) {
const username = session.getAttribute("username");
const payload = JSON.stringify({ from: username, text: message });
session.room("chat").broadcastExcept(payload);
}session.getAttributes()
Get all custom attributes as a map.
- Returns:
{ [key: string]: any }
WebSocketRoom
Rooms provide group communication. Obtain a room handle via session.room(name). The room is not auto-joined — you must explicitly call join().
session.room(roomName)
Get a room proxy for the given room name. Does not join the room — call .join() separately.
- Parameters:
roomName: string - Returns:
WebSocketRoom
room.join()
Join this room. Rooms are created lazily on first join.
javascript
session.room("lobby").join();room.leave()
Leave this room. Rooms are automatically deleted when empty.
javascript
session.room("lobby").leave();room.broadcast(message)
Send a message to all members of this room, including the sender.
- Parameters:
message: string
javascript
session.room("lobby").broadcast(JSON.stringify({
type: "announcement",
text: "Server maintenance in 5 minutes"
}));room.broadcastExcept(message)
Send a message to all room members except the sender.
- Parameters:
message: string
javascript
session.room("lobby").broadcastExcept(JSON.stringify({
type: "message",
from: session.getAttribute("username"),
text: message
}));room.members()
Get the number of members currently in this room.
- Returns:
number
javascript
const count = session.room("lobby").members();
session.send(JSON.stringify({ type: "roster", online: count }));room.getName()
Get the room name.
- Returns:
string
Lifecycle Notes
- Room memberships are automatically cleaned up when
onClosereturns, even if you don't callleave()manually. - The
send()method is synchronized on the session — thread-safe for concurrent calls. - A single session can join multiple rooms simultaneously.
- Room operations are backed by an in-memory concurrent map — no database persistence.
Full Example: Chat Room
javascript
export function onOpen(session) {
const username = session.getParameter("user") || "anonymous";
session.setAttribute("username", username);
session.room("chat").join();
session.send(JSON.stringify({ type: "welcome", id: session.id }));
session.room("chat").broadcastExcept(JSON.stringify({
type: "join",
user: username
}));
}
export function onMessage(session, message) {
const username = session.getAttribute("username");
session.room("chat").broadcastExcept(JSON.stringify({
type: "message",
from: username,
text: message,
timestamp: Date.now()
}));
}
export function onClose(session) {
const username = session.getAttribute("username");
session.room("chat").broadcastExcept(JSON.stringify({
type: "leave",
user: username
}));
// room.leave() is called automatically after onClose returns
}