- Go 99.1%
- Shell 0.9%
| autobahn | ||
| .gitignore | ||
| benchmark_test.go | ||
| close.go | ||
| close_test.go | ||
| compress.go | ||
| compress_test.go | ||
| dial.go | ||
| dial_test.go | ||
| frame.go | ||
| frame_test.go | ||
| go.mod | ||
| handshake.go | ||
| handshake_test.go | ||
| mask.go | ||
| mask_test.go | ||
| README.md | ||
| upgrade.go | ||
| upgrade_test.go | ||
| utf8.go | ||
| utf8_test.go | ||
| ws.go | ||
| ws_test.go | ||
ws
A minimal WebSocket library for Go. Zero dependencies outside the standard library.
Handles both server and client connections, supports permessage-deflate compression,
and passes the current Autobahn WebSocket test suite
configuration for crossbario/autobahn-testsuite:25.10.1 (673 passing cases across
the deflate and no-deflate testees).
go get git.sharkk.net/go/ws
Server
Use Upgrade inside any net/http handler to hijack the connection:
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
conn, err := ws.Upgrade(w, r, &ws.UpgradeOptions{
EnableDeflate: true,
})
if err != nil {
return
}
defer conn.Close()
for {
msgType, data, err := conn.ReadMessage()
if err != nil {
break
}
conn.WriteMessage(msgType, data)
}
})
UpgradeOptions lets you set allowed subprotocols, a custom origin checker, and
whether to negotiate compression. If CheckOrigin is nil it defaults to
matching the Origin header against Host.
Client
conn, resp, err := ws.Dial("ws://localhost:8080/ws", &ws.DialOptions{
EnableDeflate: true,
})
if err != nil {
log.Fatal(err)
}
defer conn.Close()
conn.WriteMessage(ws.MessageText, []byte("hello"))
msgType, data, err := conn.ReadMessage()
Dial supports ws:// and wss:// schemes, custom TLS configs, extra headers,
subprotocol negotiation, and a configurable handshake timeout (default 10s).
API
Conn methods:
| Method | What it does |
|---|---|
ReadMessage() (MessageType, []byte, error) |
Read the next complete message. Handles fragmentation, control frames, decompression, and UTF-8 validation internally. Returns a *CloseError when the peer closes. |
WriteMessage(msgType, data) |
Write a complete message. Compresses automatically when deflate is negotiated. |
WriteClose(code, reason) |
Send a close frame. |
WritePing(data) / WritePong(data) |
Send ping/pong frames. |
SetReadLimit(n) |
Set max incoming message size (default 32 MB). Sends 1009 and errors if exceeded. |
NetConn() |
Get the underlying net.Conn for deadlines, etc. |
Close() |
Close the TCP connection directly. |
Message types: ws.MessageText, ws.MessageBinary.
Close codes: ws.CloseNormalClosure, ws.CloseGoingAway, ws.CloseProtocolError, etc.
Check the close reason with a type assertion on *ws.CloseError.
Compression
When EnableDeflate is set, the library negotiates
permessage-deflate with
server_no_context_takeover and client_no_context_takeover. Flate writers and
readers are pooled with sync.Pool to keep allocations down. Compression is
transparent — ReadMessage and WriteMessage handle it automatically.
Testing
Unit tests:
go test -c -o ws_test.exe . && ./ws_test.exe -test.v
Autobahn (requires Docker via WSL on Windows):
# Cross-compile the echo server
GOOS=linux GOARCH=amd64 go build -o autobahn/echoserver_linux ./autobahn/
# Run the suite
wsl -d archlinux -- bash autobahn/run_wsl.sh
# Check results
go run autobahn/check.go autobahn/reports/index.json