WebSocket Reference
Handshake Headers
# Client Upgrade Request
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
# Server Response (101 Switching Protocols)
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
JavaScript WebSocket API
const ws = new WebSocket('wss://example.com/socket');
// Connection opened
ws.addEventListener('open', (event) => {
ws.send(JSON.stringify({ type: 'subscribe', channel: 'news' }));
});
// Listen for messages
ws.addEventListener('message', (event) => {
const data = JSON.parse(event.data);
console.log('Message:', data);
});
// Handle errors
ws.addEventListener('error', (event) => {
console.error('WebSocket error:', event);
});
// Connection closed
ws.addEventListener('close', (event) => {
console.log(`Closed: code=${event.code}, reason=${event.reason}`);
});
// Send binary data
ws.send(new Uint8Array([1, 2, 3]).buffer);
// Close connection
ws.close(1000, 'Normal closure');
Close Codes
| Code | Name | Description |
|---|---|---|
| 1000 | Normal Closure | Successful operation, connection done |
| 1001 | Going Away | Server shutting down or client navigating away |
| 1002 | Protocol Error | Protocol error encountered |
| 1003 | Unsupported Data | Unacceptable data type received |
| 1006 | Abnormal Closure | Connection closed abnormally (no close frame) |
| 1007 | Invalid Frame | Non-UTF-8 data in text message |
| 1008 | Policy Violation | Message violates server policy |
| 1009 | Message Too Big | Message too large to process |
| 1011 | Internal Error | Server encountered unexpected condition |
Heartbeat / Ping-Pong Pattern
// Client-side heartbeat
function createWebSocket(url) {
const ws = new WebSocket(url);
let pingInterval;
ws.addEventListener('open', () => {
pingInterval = setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ type: 'ping' }));
}
}, 30000); // ping every 30s
});
ws.addEventListener('message', (event) => {
const msg = JSON.parse(event.data);
if (msg.type === 'pong') return; // ignore pongs
// handle real messages
});
ws.addEventListener('close', () => {
clearInterval(pingInterval);
setTimeout(() => createWebSocket(url), 3000); // reconnect
});
return ws;
}
Go Server Example (gorilla/websocket)
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
CheckOrigin: func(r *http.Request) bool {
return true // relax for dev; validate origin in prod
},
}
func wsHandler(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil { return }
defer conn.Close()
for {
messageType, p, err := conn.ReadMessage()
if err != nil { break }
if err := conn.WriteMessage(messageType, p); err != nil {
break
}
}
}
readyState Values
| Value | Constant | Meaning |
|---|---|---|
| 0 | CONNECTING | Socket created, not yet connected |
| 1 | OPEN | Connection is open and ready |
| 2 | CLOSING | Closing handshake in progress |
| 3 | CLOSED | Connection is closed |