WebSocket Echo (RFC 6455 from scratch)
Source: Custom
Topics: HTTP Upgrade, frame format, masking, ping/pong
Problem
Implement the WebSocket opening handshake and basic frame I/O directly on top of net/http's
hijacking support — no gorilla/websocket, no golang.org/x/net/websocket.
Requirements:
AcceptKey(key string) string — compute Sec-WebSocket-Accept = base64(sha1(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")).
Upgrade(w http.ResponseWriter, r *http.Request) (*Conn, error) — validate Sec-WebSocket-Key, hijack the connection, write the 101 Switching Protocols response with the computed accept key.
(*Conn) ReadMessage() (opcode byte, payload []byte, err error) — parse a frame: opcode, payload length (7-bit / 16-bit / 64-bit extended), and unmask if the client set the mask bit (clients always mask).
(*Conn) WriteMessage(opcode byte, payload []byte) error — write an unmasked frame (server→client frames are never masked) and flush.
Serve(c *Conn) error — echo loop: text/binary frames are echoed back; OpPing → reply OpPong; OpClose → reply OpClose and return.
Opcodes: OpText = 0x1, OpBinary = 0x2, OpClose = 0x8, OpPing = 0x9, OpPong = 0xA.
type Conn struct { ... }
func AcceptKey(key string) string
func Upgrade(w http.ResponseWriter, r *http.Request) (*Conn, error)
func (c *Conn) ReadMessage() (byte, []byte, error)
func (c *Conn) WriteMessage(opcode byte, payload []byte) error
func (c *Conn) Close() error
func Serve(c *Conn) error
Key concepts
- Handshake: the accept key proves the server understood the WebSocket protocol — it's a hash of the client's key plus a fixed magic GUID, not a secret.
- http.Hijacker: takes over the raw TCP connection from
net/http, returning a *bufio.ReadWriter for framed I/O.
- Frame format (RFC 6455 §5.2): 1 byte FIN+opcode, 1 byte MASK+length (7/16/64-bit extended length), optional 4-byte mask key, then payload.
- Masking: every byte the client sends is XORed with a 4-byte mask key included in the frame; the server never masks its frames.
Run
go test -v -race ./challenges/networking/websocket-echo/
Sign in to submit your solution.