M
.github
build: add Makefile (#525)
ci
build: add Makefile (#525)
internal
build: update to Go 1.23 (#524)
wsjson
Update import path to github.com/coder/websocket
accept_test.go
accept: Add unwrapping for hijack like http.ResponseController (#472)
accept.go
feat: add ping and pong received callbacks (#509)
autobahn_test.go
fix: conform to stricter printf usage in Go 1.24 (#508)
close_test.go
Update import path to github.com/coder/websocket
close.go
fix: avoid writing messages after close and improve handshake (#476)
compress_test.go
Update import path to github.com/coder/websocket
compress.go
Misc fixes
conn_test.go
feat: add ping and pong received callbacks (#509)
conn.go
feat: add ping and pong received callbacks (#509)
dial_test.go
Update import path to github.com/coder/websocket
dial.go
feat: add ping and pong received callbacks (#509)
doc.go
Update import path to github.com/coder/websocket
example_test.go
Update import path to github.com/coder/websocket
export_test.go
Update import path to github.com/coder/websocket
frame_test.go
Update import path to github.com/coder/websocket
frame.go
Update import path to github.com/coder/websocket
go.mod
build: update to Go 1.23 (#524)
go.sum
internal/xcpu: Vendor golang.org/x/sys/cpu
hijack_go120_test.go
accept: Add unwrapping for hijack like http.ResponseController (#472)
hijack.go
accept: Add unwrapping for hijack like http.ResponseController (#472)
LICENSE.txt
chore: update LICENSE file (#526)
main_test.go
Ensure no goroutines leak after Close
Makefile
build: add Makefile (#525)
mask_amd64.s
mask_asm: Disable AVX2
mask_arm64.s
mask_asm: Note implementation may not be perfect
mask_asm_test.go
mask.go: Revert my changes
mask_asm.go
read: Fix CloseRead to have its own done channel
mask_go.go
mask.go: Reorganize
mask_test.go
Update import path to github.com/coder/websocket
mask.go
mask_asm: Disable for now until v1.9.0
netconn_js.go
netconn.go: Return real remote and local address where possible
netconn_notjs.go
netconn.go: Return real remote and local address where possible
netconn.go
Use new atomic types from Go 1.19
read.go
feat: add ping and pong received callbacks (#509)
README.md
docs: Fix docs and examples related to r.Context() usage (#477)
stringer.go
Change websocket to WebSocket in docs/errors
write.go
fix: avoid writing messages after close and improve handshake (#476)
ws_js_test.go
Update import path to github.com/coder/websocket
ws_js.go
Merge branch 'master' into dev

websocket

websocket is a minimal and idiomatic WebSocket library for Go.

Install

go get github.com/coder/websocket

NOTE

Coder now maintains this project as explained in this blog post. We're grateful to nhooyr for authoring and maintaining this project from 2019 to 2024.

Highlights

Roadmap

See GitHub issues for minor issues but the major future enhancements are:

  • Perfect examples #217
  • wstest.Pipe for in memory testing #340
  • Ping pong heartbeat helper #267
  • Ping pong instrumentation callbacks #246
  • Graceful shutdown helpers #209
  • Assembly for WebSocket masking #16
    • WIP at #326, about 3x faster
  • HTTP/2 #4
  • The holy grail #402

Examples

For a production quality example that demonstrates the complete API, see the echo example.

For a full stack example, see the chat example.

Server

http.HandlerFunc(func (w http.ResponseWriter, r *http.Request) {
	c, err := websocket.Accept(w, r, nil)
	if err != nil {
		// ...
	}
	defer c.CloseNow()

	// Set the context as needed. Use of r.Context() is not recommended
	// to avoid surprising behavior (see http.Hijacker).
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
	defer cancel()

	var v interface{}
	err = wsjson.Read(ctx, c, &v)
	if err != nil {
		// ...
	}

	log.Printf("received: %v", v)

	c.Close(websocket.StatusNormalClosure, "")
})

Client

ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()

c, _, err := websocket.Dial(ctx, "ws://localhost:8080", nil)
if err != nil {
	// ...
}
defer c.CloseNow()

err = wsjson.Write(ctx, c, "hi")
if err != nil {
	// ...
}

c.Close(websocket.StatusNormalClosure, "")

Comparison

gorilla/websocket

Advantages of gorilla/websocket:

  • Mature and widely used
  • Prepared writes
  • Configurable buffer sizes
  • No extra goroutine per connection to support cancellation with context.Context. This costs github.com/coder/websocket 2 KB of memory per connection.

Advantages of github.com/coder/websocket:

golang.org/x/net/websocket

golang.org/x/net/websocket is deprecated. See golang/go/issues/18152.

The net.Conn can help in transitioning to github.com/coder/websocket.

gobwas/ws

gobwas/ws has an extremely flexible API that allows it to be used in an event driven style for performance. See the author's blog post.

However it is quite bloated. See https://pkg.go.dev/github.com/gobwas/ws

When writing idiomatic Go, github.com/coder/websocket will be faster and easier to use.

lesismal/nbio

lesismal/nbio is similar to gobwas/ws in that the API is event driven for performance reasons.

However it is quite bloated. See https://pkg.go.dev/github.com/lesismal/nbio

When writing idiomatic Go, github.com/coder/websocket will be faster and easier to use.