The WebSocket Handshake
18 min
A WebSocket connection begins life as a normal HTTP request with an
Upgrade: websocket header and a random client-generated key
(Sec-WebSocket-Key). The server proves it's a real WebSocket-aware
server — not just an HTTP server ignoring the Upgrade header — by
combining that key with a fixed, publicly-known "magic" GUID, hashing
it, and sending the result back as Sec-WebSocket-Accept. Only after
this exchange does the SAME underlying TCP connection switch from
HTTP framing to WebSocket framing — no new connection is opened.
import hashlib
import base64
def compute_accept_key(sec_websocket_key):
GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
combined = sec_websocket_key + GUID
sha1_digest = hashlib.sha1(combined.encode()).digest()
return base64.b64encode(sha1_digest).decode()
Because the GUID is publicly fixed and the hash is one-way, this isn't a security mechanism -- it's purely a 'yes, I am actually speaking the WebSocket protocol, not just echoing your HTTP request' handshake.
Write `compute_accept_key(sec_websocket_key)` per RFC 6455: append the magic GUID `"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"` to the client's key, take the SHA-1 hash of the result, then base64-encode it. Return the base64 string.
A WebSocket connection starts as a regular HTTP request. What actually happens during the handshake?
You can compute the WebSocket handshake's Sec-WebSocket-Accept value exactly as RFC 6455 specifies, and understand why the handshake upgrades an existing HTTP connection rather than opening a new one.