{"id":14021941,"url":"https://github.com/coder/websocket","last_synced_at":"2025-05-13T19:17:31.151Z","repository":{"id":34524852,"uuid":"144590177","full_name":"coder/websocket","owner":"coder","description":"Minimal and idiomatic WebSocket library for Go","archived":false,"fork":false,"pushed_at":"2025-03-25T12:27:10.000Z","size":1120,"stargazers_count":4343,"open_issues_count":55,"forks_count":315,"subscribers_count":41,"default_branch":"master","last_synced_at":"2025-05-08T01:55:49.896Z","etag":null,"topics":["go","http2","idiomatic","minimal","websocket"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coder.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"nhooyr"}},"created_at":"2018-08-13T14:21:01.000Z","updated_at":"2025-05-08T01:49:27.000Z","dependencies_parsed_at":"2023-10-14T19:54:33.564Z","dependency_job_id":"fdd9a82b-80a3-49cd-94e0-d0f87904b36e","html_url":"https://github.com/coder/websocket","commit_stats":{"total_commits":475,"total_committers":9,"mean_commits":52.77777777777778,"dds":"0.025263157894736876","last_synced_commit":"14fb98eba64eeb5e9d06a88b98c47ae924ac82b4"},"previous_names":["coder/websocket"],"tags_count":39,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coder%2Fwebsocket","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coder%2Fwebsocket/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coder%2Fwebsocket/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coder%2Fwebsocket/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coder","download_url":"https://codeload.github.com/coder/websocket/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254010830,"owners_count":21999004,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","http2","idiomatic","minimal","websocket"],"created_at":"2024-08-11T14:01:07.621Z","updated_at":"2025-05-13T19:17:31.124Z","avatar_url":"https://github.com/coder.png","language":"Go","readme":"# websocket\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/coder/websocket.svg)](https://pkg.go.dev/github.com/coder/websocket)\n[![Go Coverage](https://coder.github.io/websocket/coverage.svg)](https://coder.github.io/websocket/coverage.html)\n\nwebsocket is a minimal and idiomatic WebSocket library for Go.\n\n## Install\n\n```sh\ngo get github.com/coder/websocket\n```\n\n\u003e [!NOTE]\n\u003e Coder now maintains this project as explained in [this blog post](https://coder.com/blog/websocket).\n\u003e We're grateful to [nhooyr](https://github.com/nhooyr) for authoring and maintaining this project from\n\u003e 2019 to 2024.\n\n## Highlights\n\n- Minimal and idiomatic API\n- First class [context.Context](https://blog.golang.org/context) support\n- Fully passes the WebSocket [autobahn-testsuite](https://github.com/crossbario/autobahn-testsuite)\n- [Zero dependencies](https://pkg.go.dev/github.com/coder/websocket?tab=imports)\n- JSON helpers in the [wsjson](https://pkg.go.dev/github.com/coder/websocket/wsjson) subpackage\n- Zero alloc reads and writes\n- Concurrent writes\n- [Close handshake](https://pkg.go.dev/github.com/coder/websocket#Conn.Close)\n- [net.Conn](https://pkg.go.dev/github.com/coder/websocket#NetConn) wrapper\n- [Ping pong](https://pkg.go.dev/github.com/coder/websocket#Conn.Ping) API\n- [RFC 7692](https://tools.ietf.org/html/rfc7692) permessage-deflate compression\n- [CloseRead](https://pkg.go.dev/github.com/coder/websocket#Conn.CloseRead) helper for write only connections\n- Compile to [Wasm](https://pkg.go.dev/github.com/coder/websocket#hdr-Wasm)\n\n## Roadmap\n\nSee GitHub issues for minor issues but the major future enhancements are:\n\n- [ ] Perfect examples [#217](https://github.com/nhooyr/websocket/issues/217)\n- [ ] wstest.Pipe for in memory testing [#340](https://github.com/nhooyr/websocket/issues/340)\n- [ ] Ping pong heartbeat helper [#267](https://github.com/nhooyr/websocket/issues/267)\n- [ ] Ping pong instrumentation callbacks [#246](https://github.com/nhooyr/websocket/issues/246)\n- [ ] Graceful shutdown helpers [#209](https://github.com/nhooyr/websocket/issues/209)\n- [ ] Assembly for WebSocket masking [#16](https://github.com/nhooyr/websocket/issues/16)\n  - WIP at [#326](https://github.com/nhooyr/websocket/pull/326), about 3x faster\n- [ ] HTTP/2 [#4](https://github.com/nhooyr/websocket/issues/4)\n- [ ] The holy grail [#402](https://github.com/nhooyr/websocket/issues/402)\n\n## Examples\n\nFor a production quality example that demonstrates the complete API, see the\n[echo example](./internal/examples/echo).\n\nFor a full stack example, see the [chat example](./internal/examples/chat).\n\n### Server\n\n```go\nhttp.HandlerFunc(func (w http.ResponseWriter, r *http.Request) {\n\tc, err := websocket.Accept(w, r, nil)\n\tif err != nil {\n\t\t// ...\n\t}\n\tdefer c.CloseNow()\n\n\t// Set the context as needed. Use of r.Context() is not recommended\n\t// to avoid surprising behavior (see http.Hijacker).\n\tctx, cancel := context.WithTimeout(context.Background(), time.Second*10)\n\tdefer cancel()\n\n\tvar v interface{}\n\terr = wsjson.Read(ctx, c, \u0026v)\n\tif err != nil {\n\t\t// ...\n\t}\n\n\tlog.Printf(\"received: %v\", v)\n\n\tc.Close(websocket.StatusNormalClosure, \"\")\n})\n```\n\n### Client\n\n```go\nctx, cancel := context.WithTimeout(context.Background(), time.Minute)\ndefer cancel()\n\nc, _, err := websocket.Dial(ctx, \"ws://localhost:8080\", nil)\nif err != nil {\n\t// ...\n}\ndefer c.CloseNow()\n\nerr = wsjson.Write(ctx, c, \"hi\")\nif err != nil {\n\t// ...\n}\n\nc.Close(websocket.StatusNormalClosure, \"\")\n```\n\n## Comparison\n\n### gorilla/websocket\n\nAdvantages of [gorilla/websocket](https://github.com/gorilla/websocket):\n\n- Mature and widely used\n- [Prepared writes](https://pkg.go.dev/github.com/gorilla/websocket#PreparedMessage)\n- Configurable [buffer sizes](https://pkg.go.dev/github.com/gorilla/websocket#hdr-Buffers)\n- No extra goroutine per connection to support cancellation with context.Context. This costs github.com/coder/websocket 2 KB of memory per connection.\n  - Will be removed soon with [context.AfterFunc](https://github.com/golang/go/issues/57928). See [#411](https://github.com/nhooyr/websocket/issues/411)\n\nAdvantages of github.com/coder/websocket:\n\n- Minimal and idiomatic API\n  - Compare godoc of [github.com/coder/websocket](https://pkg.go.dev/github.com/coder/websocket) with [gorilla/websocket](https://pkg.go.dev/github.com/gorilla/websocket) side by side.\n- [net.Conn](https://pkg.go.dev/github.com/coder/websocket#NetConn) wrapper\n- Zero alloc reads and writes ([gorilla/websocket#535](https://github.com/gorilla/websocket/issues/535))\n- Full [context.Context](https://blog.golang.org/context) support\n- Dial uses [net/http.Client](https://golang.org/pkg/net/http/#Client)\n  - Will enable easy HTTP/2 support in the future\n  - Gorilla writes directly to a net.Conn and so duplicates features of net/http.Client.\n- Concurrent writes\n- Close handshake ([gorilla/websocket#448](https://github.com/gorilla/websocket/issues/448))\n- Idiomatic [ping pong](https://pkg.go.dev/github.com/coder/websocket#Conn.Ping) API\n  - Gorilla requires registering a pong callback before sending a Ping\n- Can target Wasm ([gorilla/websocket#432](https://github.com/gorilla/websocket/issues/432))\n- Transparent message buffer reuse with [wsjson](https://pkg.go.dev/github.com/coder/websocket/wsjson) subpackage\n- [1.75x](https://github.com/nhooyr/websocket/releases/tag/v1.7.4) faster WebSocket masking implementation in pure Go\n  - Gorilla's implementation is slower and uses [unsafe](https://golang.org/pkg/unsafe/).\n    Soon we'll have assembly and be 3x faster [#326](https://github.com/nhooyr/websocket/pull/326)\n- Full [permessage-deflate](https://tools.ietf.org/html/rfc7692) compression extension support\n  - Gorilla only supports no context takeover mode\n- [CloseRead](https://pkg.go.dev/github.com/coder/websocket#Conn.CloseRead) helper for write only connections ([gorilla/websocket#492](https://github.com/gorilla/websocket/issues/492))\n\n#### golang.org/x/net/websocket\n\n[golang.org/x/net/websocket](https://pkg.go.dev/golang.org/x/net/websocket) is deprecated.\nSee [golang/go/issues/18152](https://github.com/golang/go/issues/18152).\n\nThe [net.Conn](https://pkg.go.dev/github.com/coder/websocket#NetConn) can help in transitioning\nto github.com/coder/websocket.\n\n#### gobwas/ws\n\n[gobwas/ws](https://github.com/gobwas/ws) has an extremely flexible API that allows it to be used\nin an event driven style for performance. See the author's [blog post](https://medium.freecodecamp.org/million-websockets-and-go-cc58418460bb).\n\nHowever it is quite bloated. See https://pkg.go.dev/github.com/gobwas/ws\n\nWhen writing idiomatic Go, github.com/coder/websocket will be faster and easier to use.\n\n#### lesismal/nbio\n\n[lesismal/nbio](https://github.com/lesismal/nbio) is similar to gobwas/ws in that the API is\nevent driven for performance reasons.\n\nHowever it is quite bloated. See https://pkg.go.dev/github.com/lesismal/nbio\n\nWhen writing idiomatic Go, github.com/coder/websocket will be faster and easier to use.\n","funding_links":["https://github.com/sponsors/nhooyr"],"categories":["Go"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoder%2Fwebsocket","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoder%2Fwebsocket","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoder%2Fwebsocket/lists"}