ws

A zero-allocation Go library for building fast, low-level RFC 6455 WebSocket servers and clients.

Library
Go
vv1.4.0
6,467stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
47/100Fair
Development Activity4
Maintenance20
Community64
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
76/100Good
Architecture78
Code Quality85
Innovation75
Learning Curve65

ws is a minimal, low-level implementation of the RFC 6455 WebSocket protocol for Go, built around the idea that WebSocket libraries shouldn’t force allocations or copying onto every connection. Instead of hiding the protocol behind a single high-level Conn type, ws exposes granular primitives for reading and writing frames, performing the HTTP handshake, and masking/unmasking payloads, letting the caller control buffer reuse and connection handling directly.

A zero-copy “Upgrader” performs the WebSocket handshake in place using caller-registered callbacks (OnHeader, OnHost, OnBeforeUpgrade) so non-WebSocket headers never need to be allocated or copied unnecessarily. For teams that don’t need that level of control, the companion wsutil subpackage layers ergonomic Reader/Writer/Handler abstractions on top, and wsflate adds permessage-deflate compression support. The library has no dependencies beyond two sibling gobwas packages and passes the Autobahn Test Suite for full protocol conformance, making it a common building block for high-connection-count realtime services written in Go.

What You Get

  • Zero-copy HTTP upgrade via a callback-driven Upgrader (OnHeader, OnHost, OnBeforeUpgrade) that avoids allocating for headers the caller doesn’t need
  • Low-level frame-level API (ReadHeader/WriteHeader, Cipher masking) for building custom connection handling and buffer-reuse strategies
  • A higher-level wsutil subpackage with Reader/Writer/Handler wrappers for teams that want convenience over raw control
  • A wsflate subpackage implementing the permessage-deflate compression extension
  • A purego build-tag escape hatch to disable unsafe pointer tricks in restricted environments
  • Full RFC 6455 conformance verified continuously against the Autobahn Test Suite

Common Use Cases

  • Building high-connection-count realtime servers (chat, notifications, live dashboards) where per-connection allocation overhead matters
  • Implementing a custom WebSocket gateway or proxy that needs to inspect/reject handshakes based on headers before upgrading
  • Adding WebSocket support to an existing net/http server via the standard Hijacker-based upgrade path
  • Writing WebSocket clients that stream structured (e.g. JSON) messages over persistent connections using the wsutil Reader/Writer pair
  • Embedding WebSocket transport inside a larger low-level networking service that already manages its own buffer pools

Under The Hood

Architecture The library is organized as a flat top-level ws package holding the core protocol primitives (frame.go, cipher.go, check.go, nonce.go), HTTP upgrade handling (http.go, server.go, dialer.go, with Go-version-specific variants like hijack_go119.go/hijack_go120.go and dialer_tls_go17.go/dialer_tls_go18.go for backward compatibility), and low-level utilities gated by build tags (util_unsafe.go vs util_purego.go for unsafe-vs-safe string/byte conversion). Higher-level ergonomic wrappers live in the separate wsutil subpackage, and a wsflate subpackage implements the permessage-deflate extension, giving the codebase a clear layered structure: raw protocol at the root, convenience abstractions in wsutil, and extensions in wsflate. Data flows directly through the caller-supplied net.Conn with no hidden internal buffering; the Upgrader’s OnHeader/OnHost/OnBeforeUpgrade callback hooks let callers intercept the zero-copy HTTP upgrade in place. Changing the core Header/frame representation would ripple through wsutil, wsflate, and every callback signature, but callers who only use wsutil stay insulated from most root-package churn.

Tech Stack Pure Go (go.mod targets go1.16) with zero external dependencies beyond two sibling gobwas packages — github.com/gobwas/httphead for header parsing and github.com/gobwas/pool for buffer pooling (via pbufio) — plus an indirect golang.org/x/sys dependency. There is no web framework in play; the library plugs directly into net/http via the Hijacker interface or into a raw net.Conn. Build tooling is a plain Makefile driving go test/go vet/golangci-lint, and a dedicated Autobahn Test Suite integration (autobahn/ directory plus a GitHub Actions “Autobahn” workflow) runs full RFC 6455 conformance checks on every push and pull request across both the current and previous stable Go versions.

Code Quality The repository carries an extensive test suite — ten top-level *_test.go files covering ciphering, dialing, framing, HTTP handling, nonces, reading, writing, and utility functions, plus further test files inside the wsutil and wsflate subpackages — all using the standard library testing package with table-driven cases, no external assertion dependency. Error handling is explicit and idiomatic: sentinel errors and a typed ConnectionRejectedError with a documented RejectConnectionError/RejectOption pattern for controlling handshake rejection, rather than panics. Exported identifiers carry consistent godoc comments, backed by a package-level doc.go overview. Type safety is strong throughout the core path, and the one genuinely unsafe optimization (string/byte conversion) is isolated behind a build tag so it can be disabled entirely via the purego tag.

What Makes It Unique What sets ws apart from other Go WebSocket libraries is its explicit zero-copy, zero-allocation design philosophy: the Upgrader’s granular callback hooks let a caller inspect and reject a handshake in place without allocating for headers it doesn’t care about, and the low-level ReadHeader/WriteHeader frame API hands buffer-reuse responsibility directly to the caller instead of hiding it behind a high-level connection wrapper — a deliberate trade of ergonomics for control aimed at high-connection-count servers. The library backs this low-level surface with continuous Autobahn Test Suite conformance testing and ships a purego build-tag escape hatch for environments where unsafe pointer tricks are undesirable.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search