Skip to content

A small, gorilla-free WebSocket server for Go — clean API, RFC6455 handshake, frames, ping/pong keepalive, JSON helpers, and a simple room hub. Built to be extended (rate limiting, metrics, distributed hub) without leaking third-party types into your code.

License

Notifications You must be signed in to change notification settings

aminofox/zsocket

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

zsocket

A small, gorilla-free WebSocket server for Go — clean API, RFC6455 handshake, frames, ping/pong keepalive, JSON helpers, and a simple room hub. Built to be extended (rate limiting, metrics, distributed hub) without leaking third-party types into your code.

Module: github.com/aminofox/zsocket

Features

  • Minimal RFC6455 server-side implementation
  • Clean API:
    • Accept(w, r, cfg) (*Conn, error)
    • Conn.Read(ctx) (MessageType, []byte, error)
    • Conn.Write(ctx, mt, data)
    • Conn.ReadJSON/WriteJSON
    • Conn.Close(code, reason)
    • Conn.Subprotocol(), Conn.RemoteAddr()
  • Fragmentation (basic accumulation until FIN)
  • Control frames: ping/pong/close
  • Keepalive: PingInterval + PongWait
  • Hub: rooms & broadcast
  • Configurable read limit, deadlines, origin policy, subprotocols

Quick Start

go get github.com/aminofox/zsocket
package main

import (
  "context"
  "log"
  "net/http"
  "github.com/aminofox/zsocket"
)

func main() {
  cfg := zsocket.DefaultConfig()
  hub := zsocket.NewHub()

  http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
    conn, err := zsocket.Accept(w, r, cfg)
    if err != nil {
      http.Error(w, "upgrade failed", http.StatusBadRequest)
      return
    }
    hub.Join("lobby", conn)

    go func() {
      defer func() {
        hub.LeaveAll(conn)
        _ = conn.Close(zsocket.CloseNormalClosure, "bye")
      }()
      ctx := context.Background()
      _ = conn.Write(ctx, zsocket.TextMessage, []byte("hello from zsocket"))

      for {
        mt, msg, err := conn.Read(ctx)
        if err != nil {
          log.Printf("read: %v", err)
          return
        }
        _ = conn.Write(ctx, mt, msg) // echo
        hub.Broadcast(ctx, "lobby", mt, msg)
      }
    }()
  })

  log.Fatal(http.ListenAndServe(":8080", nil))
}

Config

cfg := zsocket.DefaultConfig()
cfg.AllowedOrigins = []string{"https://example.com"} // or nil to allow all
cfg.Subprotocols = []string{"chat", "json"}
cfg.ReadLimit = 16 << 20  // 16 MiB per message
cfg.PingInterval = 30 * time.Second
cfg.PongWait = 15 * time.Second
cfg.WriteTimeout = 10 * time.Second

JSON Helpers

type In struct { Cmd string `json:"cmd"`; Body any `json:"body"` }

var in In
if err := conn.ReadJSON(ctx, &in); err != nil { ... }
if err := conn.WriteJSON(ctx, map[string]any{"ok": true}); err != nil { ... }

Rooms & Broadcast

hub.Join("room-42", conn)
hub.Broadcast(ctx, "room-42", zsocket.TextMessage, []byte("hi all"))
hub.Leave("room-42", conn)

About

A small, gorilla-free WebSocket server for Go — clean API, RFC6455 handshake, frames, ping/pong keepalive, JSON helpers, and a simple room hub. Built to be extended (rate limiting, metrics, distributed hub) without leaking third-party types into your code.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages