gorilla/websocket
Package gorilla/websocket is a fast, well-tested and widely used WebSocket implementation for Go.
Stale — last commit 1y ago
worst of 4 axeslast commit was 1y ago; no tests detected…
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
last commit was 1y ago; no CI workflows detected
- ✓47+ active contributors
- ✓Distributed ownership (top contributor 9% of recent commits)
- ✓BSD-2-Clause licensed
Show 3 more →Show less
- ⚠Stale — last commit 1y ago
- ⚠No CI workflows detected
- ⚠No test directory detected
What would change the summary?
- →Use as dependency Mixed → Healthy if: 1 commit in the last 365 days; add a test suite
- →Deploy as-is Mixed → Healthy if: 1 commit in the last 180 days
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/gorilla/websocket)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/gorilla/websocket on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: gorilla/websocket
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/gorilla/websocket shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
WAIT — Stale — last commit 1y ago
- 47+ active contributors
- Distributed ownership (top contributor 9% of recent commits)
- BSD-2-Clause licensed
- ⚠ Stale — last commit 1y ago
- ⚠ No CI workflows detected
- ⚠ No test directory detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live gorilla/websocket
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/gorilla/websocket.
What it runs against: a local clone of gorilla/websocket — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in gorilla/websocket | Confirms the artifact applies here, not a fork |
| 2 | License is still BSD-2-Clause | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 446 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of gorilla/websocket. If you don't
# have one yet, run these first:
#
# git clone https://github.com/gorilla/websocket.git
# cd websocket
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of gorilla/websocket and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "gorilla/websocket(\\.git)?\\b" \\
&& ok "origin remote is gorilla/websocket" \\
|| miss "origin remote is not gorilla/websocket (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(BSD-2-Clause)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"BSD-2-Clause\"" package.json 2>/dev/null) \\
&& ok "license is BSD-2-Clause" \\
|| miss "license drift — was BSD-2-Clause at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "conn.go" \\
&& ok "conn.go" \\
|| miss "missing critical file: conn.go"
test -f "server.go" \\
&& ok "server.go" \\
|| miss "missing critical file: server.go"
test -f "client.go" \\
&& ok "client.go" \\
|| miss "missing critical file: client.go"
test -f "compression.go" \\
&& ok "compression.go" \\
|| miss "missing critical file: compression.go"
test -f "mask.go" \\
&& ok "mask.go" \\
|| miss "missing critical file: mask.go"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 446 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~416d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/gorilla/websocket"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Gorilla WebSocket is a production-grade RFC 6455-compliant WebSocket implementation for Go that provides fast, bidirectional communication between web clients and servers. It handles frame masking, compression (deflate), message routing, and connection lifecycle management with no external C dependencies—pure Go with optional assembly optimization in mask.go for throughput. Flat package structure: core implementation in conn.go (Conn type), client.go (Dialer), server.go (Upgrader), with supporting modules for compression.go, mask.go, prepared.go (message caching). Examples/ directory contains 4 runnable demos (chat, echo, command, filewatch) and autobahn compliance testing. No internal/ subdirectories—minimal layering.
👥Who it's for
Go backend engineers building real-time applications (chat systems, live dashboards, collaborative tools) who need a battle-tested WebSocket library that passes the Autobahn test suite. Also used by framework authors integrating WebSocket support into higher-level routers.
🌱Maturity & risk
Highly mature and production-ready. The package has a stable API (stated in README), passes the full Autobahn Test Suite (examples/autobahn), includes comprehensive test coverage across conn_test.go, client_test.go, server_test.go, and uses CircleCI for continuous integration. Go 1.20 minimum, actively maintained with only 1 retracted version (v1.5.2) in history.
Standard open source risks apply.
Active areas of work
Unable to determine from file data alone (no recent commit timestamps or PR list visible). Repo is marked stable in README with locked go.mod (golang.org/x/net v0.26.0), suggesting maintenance mode rather than active feature development. CircleCI config present indicates ongoing CI/CD validation.
🚀Get running
git clone https://github.com/gorilla/websocket && cd websocket && go mod download && go test ./... (or run a specific example: cd examples/chat && go run main.go hub.go client.go)
Daily commands: For echo server: cd examples/echo && go run server.go, then in another terminal: go run client.go. For chat: cd examples/chat && go run main.go hub.go client.go, then open http://localhost:8000. Run all tests: go test -v ./...
🗺️Map of the codebase
conn.go— Core WebSocket connection handler managing read/write loops, message framing, and lifecycle—every contributor must understand the connection state machine.server.go— HTTP upgrade handler and server-side connection establishment; essential for understanding how WebSocket handshakes are processed.client.go— Client-side dialer and connection initiation logic; critical for understanding bidirectional communication setup.compression.go— WebSocket Per-Message Deflate (PMD) compression implementation; load-bearing for protocol compliance and performance.mask.go— Frame masking logic required by RFC 6455 for client-to-server messages; security and protocol correctness depend on this.util.go— Low-level frame parsing, opcode handling, and utility functions underlying all message processing.
🧩Components & responsibilities
- Upgrader — Validates HTTP Upgrade request, performs WebSocket handshake (Sec-WebSocket-Key/Accept),
🛠️How to make changes
Add a Custom Message Handler
- Define a new message type constant in the handler logic or use existing opcodes (text=1, binary=2, ping=9, pong=10, close=8) (
conn.go) - In your application, call conn.ReadMessage() in a loop to receive messages and dispatch based on opcode (
conn.go) - For responses, call conn.WriteMessage(opcode, payload) with the appropriate opcode and data (
conn.go) - See examples/echo/server.go for a reference pattern of message read/write loops (
examples/echo/server.go)
Enable Per-Message Deflate Compression
- When creating a server, configure the Upgrader with CompressionLevel set (0-9) to enable deflate negotiation (
server.go) - Review RFC 7692 server extension parameters in compression.go to understand negotiation (
compression.go) - The connection will transparently compress/decompress if both client and server support it; no application code changes required (
conn.go)
Build a Hub-Based Broadcast Server
- Create a Hub struct with channels for register, unregister, and broadcast (see examples/chat/hub.go for pattern) (
examples/chat/hub.go) - In your HTTP handler, upgrade the connection with server.Upgrader.Upgrade() and pass it to a client goroutine (
server.go) - Client goroutine reads from conn.ReadMessage() and sends to hub.broadcast channel; hub forwards to all registered clients (
examples/chat/client.go) - Use conn.WriteJSON() for convenience or conn.WriteMessage() for lower-level control (
json.go)
Connect to a Remote WebSocket Server
- Use websocket.Dialer.Dial(url) to initiate a client connection; configure TLS and timeouts in the Dialer struct (
client.go) - For HTTP proxies, set the Dialer.Proxy field to a function that returns a proxy URL (
proxy.go) - After Dial returns, use the resulting *Conn to read/write messages with ReadMessage/WriteMessage (
conn.go) - See examples/echo/client.go for a reference client implementation (
examples/echo/client.go)
🔧Why these technologies
- Go goroutines & channels — Lightweight concurrency model ideal for handling many simultaneous WebSocket connections; channels provide safe inter-goroutine communication without locks.
- stdlib net/http upgrade mechanism — RFC 7230 / RFC 6455 compliant HTTP/1.1 upgrade path; integrates seamlessly with existing Go HTTP servers.
- compress/flate (standard library) — Provides DEFLATE streams for RFC 7692 Per-Message Deflate extension; no external compression dependency.
- golang.org/x/net — Provides low-level socket and network utilities; golang.org/x/net/proxy for HTTP CONNECT proxy support.
⚖️Trade-offs already made
-
Synchronous message-at-a-time API (ReadMessage/WriteMessage) rather than streaming or async callbacks
- Why: Simplicity and explicit control flow; user code reads in a loop, making backpressure and error handling straightforward.
- Consequence: Application must manage its own goroutines to avoid blocking one connection stalling others; pattern is verbose but gives fine-grained control.
-
Frame-level masking and framing handled internally; not exposed to application code
- Why: RFC 6455 compliance and security (client-to-server masking) are non-negotiable; hiding complexity reduces bugs.
- Consequence: Lower-level frame manipulation is not supported; all I/O goes through defined opcode-based message methods.
-
Per-connection state machine rather than pluggable message handlers
- Why: Encourages explicit goroutine-per-connection patterns that scale well and integrate with idiomatic Go concurrency.
- Consequence: No built-in pub/sub or centralized dispatcher; applications must implement their own Hub pattern (see examples/chat).
🚫Non-goals (don't propose these)
- Does not provide authentication or authorization—security is delegated to the HTTP upgrade handler and application layer.
- Does not handle automatic reconnection or client failover—applications must implement retry logic.
- Does not support HTTP/2 Server Push or WebSocket over HTTP/2 (h2c)—strictly RFC 6455 WebSocket.
- Does not provide a pub/sub framework—applications must implement their own message routing (see Hub pattern in examples).
- Does not support custom protocol subprotocols negotiation within the library—only raw WebSocket frames.
🪤Traps & gotchas
No explicit configuration files (config.yml in .circleci is CI-specific). Message masking is asymmetric: client frames are masked, server frames are not (per RFC 6455)—violating this silently breaks interop. Conn.ReadMessage/WriteMessage block until I/O completes; don't call from the same goroutine twice concurrently without external sync. No built-in connection pooling or session persistence—applications must manage Conn lifecycle manually. Autobahn fuzzing config (autobahn/config/fuzzingclient.json) is read-only reference; server.go must be running for tests.
🏗️Architecture
💡Concepts to learn
- WebSocket Frame Masking (RFC 6455 §5.3) — Client-to-server frames must be XOR-masked; gorilla/websocket handles this in mask.go with optional assembly optimization—understanding masking asymmetry is critical for debugging interop issues
- HTTP Upgrade (RFC 7230 §6.7) — WebSocket negotiation starts with HTTP 101 Switching Protocols handshake in server.go—you must understand the upgrade request/response flow to modify server-side logic
- DEFLATE Compression (RFC 7692) — gorilla/websocket supports per-message DEFLATE via compression.go for bandwidth reduction; understanding compression negotiation and frame decompression is essential for optimizing large-message workloads
- Goroutine Concurrency Patterns — conn.go uses non-blocking I/O with goroutine-per-connection; modifying connection handling requires understanding Go's concurrency primitives (channels, sync.Mutex in broadcast patterns)
- Message Fragmentation & Control Frames — WebSocket supports fragmented messages and control frames (ping/pong, close); conn.go's Read/Write methods interleave these—critical for implementing proper graceful shutdown and keepalive logic
- Prepared Messages (Optimization Pattern) — prepared.go caches marshaled frames to avoid re-encoding in high-throughput scenarios; understanding this pattern is key for performance-critical broadcast systems (see examples/chat/hub.go)
- Backpressure & Non-Blocking I/O — Slow readers can block writers in conn.go; conn.SetReadDeadline() and conn.SetWriteDeadline() are essential for preventing connection deadlocks under load
🔗Related repos
gorilla/mux— Companion Gorilla library for HTTP routing; commonly used together with gorilla/websocket to multiplex WebSocket and REST endpointsnhooyr/websocket— Alternative Go WebSocket library with context.Context-first API and automatic fragmentation; direct competitor in the ecosystemfasthttp/websocket— FastHTTP-based WebSocket implementation; alternative for ultra-low-latency scenarios using fasthttp instead of net/httpcrossbario/autobahn-testsuite— External compliance test suite (referenced in examples/autobahn/) that validates gorilla/websocket against RFC 6455golang/net— Upstream dependency (golang.org/x/net v0.26.0 in go.mod) providing net.Conn primitives and TLS support
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive benchmarks for mask operations and frame parsing
The repo has mask.go and mask_safe.go with corresponding tests, but no performance benchmarks. Given that masking is a critical path operation in WebSocket communication, adding benchmarks would help contributors understand performance trade-offs between the safe and optimized implementations, and prevent regressions in future changes.
- [ ] Create mask_bench_test.go with benchmarks for mask/unmask operations comparing mask.go vs mask_safe.go
- [ ] Add frame parsing benchmarks in conn_bench_test.go for ReadMessage/WriteMessage operations
- [ ] Document benchmark results in a new BENCHMARKS.md section explaining performance characteristics
- [ ] Add benchmark execution to .circleci/config.yml to track performance over time
Add integration tests for proxy scenarios with real TLS connections
The repo has client_proxy_server_test.go but it only tests HTTP CONNECT proxying. Given that proxy.go exists and WebSocket over TLS proxies is a common production use case, adding tests for HTTPS proxies and certificate validation scenarios would improve reliability for users in enterprise environments.
- [ ] Expand client_proxy_server_test.go with TestProxyWithTLS and TestProxyWithInvalidCert test cases
- [ ] Add helper functions to generate temporary self-signed certificates for testing
- [ ] Test both HTTP and HTTPS proxy scenarios with the actual proxy.go implementation
- [ ] Verify proxy header handling and authentication edge cases documented in proxy.go
Add compression benchmarks and interoperability tests with strict compression settings
The compression.go file has basic tests in compression_test.go, but lacks benchmarks for different compression levels and no tests verifying compatibility with clients using non-default compression parameters (deflate-frame with custom window bits). This is valuable as compression is a performance-sensitive feature that needs validation.
- [ ] Create compression_bench_test.go with benchmarks for different compression levels and message sizes
- [ ] Add tests in compression_test.go for per-message-deflate with various parameter combinations (window bits, memory level)
- [ ] Test compression behavior with conn_test.go integration tests for round-trip message integrity
- [ ] Document compression performance characteristics in examples/echo/server.go with a compression flag example
🌿Good first issues
- Add benchmarks for mask.go performance across message sizes (1KB, 64KB, 1MB) and compare mask.go (with assembly) vs mask_safe.go—file exists but no benchmark suite visible in *_test.go files.
- Expand compression_test.go with table-driven tests for edge cases: zero-length frames, rapid compression/decompression cycles, and concurrent compression on same Conn (currently minimal coverage).
- Document the Prepared message pattern (prepared.go exists but example is minimal)—add a runnable example in examples/ showing prepared message reuse in a high-throughput scenario with benchmarks.
⭐Top contributors
Click to expand
Top contributors
- @rfyiamcool — 9 commits
- @apoorvajagtap — 8 commits
- @garyburd — 8 commits
- [@Canelo Hill](https://github.com/Canelo Hill) — 7 commits
- @elithrar — 7 commits
📝Recent commits
Click to expand
Recent commits
e064f32— Implements HTTPS proxy functionality (seans3)5e00238— Do not timeout when WriteControl deadline is zero (Martin Greenwald)c5b8b8c— perf: reduce timer in write_control (rfyiamcool)f01629e— perf: reduce timer in write_control (rfyiamcool)85fb2d8— Fix typos (szepeviktor)3810b23— Handle errcheck warnings (Canelo Hill)a62d9d2— Handle net.Error Temporary() deprecation (tebuka)682b25f— Move doHandshake to client.go (tebuka)8915bad— Improve bufio handling in Upgrader.Upgrade (Canelo Hill)d67f418— Use crypto/rand for mask key (Halo Arrow)
🔒Security observations
The gorilla/websocket codebase demonstrates good security practices with no critical vulnerabilities identified in the static analysis. The main concerns are: (1) the Go version target is outdated (1.20), which should be updated to receive ongoing security patches; (2) the transitive dependency golang.org/x/net should be regularly audited; (3) the absence of a SECURITY.md file limits responsible vulnerability disclosure; (4) WebSocket-specific DoS protections should be verified in the implementation. The library is mature and widely used, suggesting it has undergone security review, but these maintenance items should be addressed.
- Medium · Outdated Go Version Target —
go.mod. The module targets Go 1.20, which is no longer actively supported. Go 1.20 reached end-of-life on August 8, 2023. Using outdated Go versions may miss critical security patches and bug fixes available in newer releases. Fix: Update the Go version to at least 1.21 or later. Review the Go release notes for any breaking changes and test thoroughly before upgrading. - Medium · Transitive Dependency Version —
go.mod. The dependency golang.org/x/net v0.26.0 is pinned to a specific version without upper bound constraints. While v0.26.0 is relatively recent, periodic audits should be performed to ensure no security vulnerabilities exist in this critical networking library. Fix: Regularly run 'go list -json -m all | nancy sleuth' or 'go mod tidy && go mod graph' to audit dependencies. Consider using 'go get -u golang.org/x/net' periodically to stay updated with security patches. - Low · Lack of Security Policy Documentation —
Repository root. No visible SECURITY.md or security policy file in the repository structure. This makes it harder for security researchers to responsibly disclose vulnerabilities. Fix: Create a SECURITY.md file documenting the process for reporting security vulnerabilities. Include contact information and expected response times. Example: https://docs.github.com/en/code-security/getting-started/adding-a-security-policy-to-your-repository - Low · Potential Denial of Service via Large Messages —
conn.go. WebSocket implementations are susceptible to DoS attacks through large message frames. Based on common WebSocket patterns, the codebase should implement message size limits, but this should be verified in conn.go. Fix: Verify that message size limits are properly enforced. Implement or configure MaxMessageSize and ensure per-connection and per-frame limits are in place to prevent memory exhaustion attacks.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.