websocket-relay/README.md
savinmax 905c241daa
Some checks failed
CI / test (push) Successful in 54s
CI / lint (push) Failing after 3m16s
Improve reliability, testing, and documentation
- Fix metrics: change MessagesTotal, ConnectionsTotal, DisconnectionsTotal
  from Gauge to Counter with proper _total naming convention
- Fix broadcast write-error handling: failed clients now get properly
  removed with accurate metrics updates
- Add graceful shutdown: SIGINT/SIGTERM handling with 10s timeout,
  CloseGoingAway frame sent to clients before disconnect
- Add integration tests: 11 tests using real WebSocket connections
  covering connect, broadcast, disconnect, concurrency, and shutdown
- Fix example client port: changed from 8000 to 8443 to match config
- Rewrite README.md to reflect current features and usage
- Add AGENTS.md and .agents/summary/ documentation for AI assistants
2026-06-11 19:14:19 +02:00

3.2 KiB

WebSocket Relay Server

A minimal Go WebSocket relay server that broadcasts every incoming message to all connected clients. Supports TLS, Prometheus metrics, and graceful shutdown.

Features

  • Fan-out broadcasting — every message is relayed to all connected clients
  • TLS support — optional wss:// via cert/key PEM files
  • Prometheus metrics — connection counts, message totals, disconnections
  • Graceful shutdown — clean exit on SIGINT/SIGTERM with client notification
  • Zero dependencies at runtime — single static binary

Quick Start

# Install dependencies
go mod tidy

# Run the server (defaults to ws://localhost:8443)
make run

# Or with a custom config
go run . --config-file=./config.yaml

Open example/index.html in multiple browser tabs to test the P2P chat demo.

Configuration

Edit config.yaml:

server:
  port: 8443
  tls:
    enabled: false       # Set true for wss://
    cert_file: cert.pem
    key_file: key.pem

metrics:
  enabled: true
  port: 9090            # Prometheus metrics at :9090/metrics

Override the config file path with --config-file:

./websocket-relay --config-file=/etc/relay/config.yaml

Usage

Connect any WebSocket client to the server:

const ws = new WebSocket('ws://localhost:8443/');

ws.onmessage = (event) => console.log('Received:', event.data);
ws.onopen = () => ws.send('Hello from client!');

With TLS enabled:

const ws = new WebSocket('wss://localhost:8443/');

All messages sent by any client are broadcast to every connected client (including the sender).

Build

make build      # Build binary → build/websocket-relay
make release    # Cross-compile linux/amd64 + darwin/arm64
make clean      # Remove build artifacts

Testing

make test       # Run all tests (unit + integration)

Metrics

When metrics.enabled is true, Prometheus metrics are exposed at http://localhost:9090/metrics:

Metric Type Description
websocket_connected_clients Gauge Currently connected clients
websocket_messages_total Counter Total messages relayed
websocket_connections_total Counter Total connections established
websocket_disconnections_total Counter Total disconnections

Graceful Shutdown

The server handles SIGINT and SIGTERM signals:

  1. Stops accepting new connections
  2. Sends WebSocket CloseGoingAway frame to all connected clients
  3. Closes all connections and exits cleanly

Shutdown timeout is 10 seconds.

Project Structure

websocket-relay/
├── main.go                  # Entry point, signal handling, graceful shutdown
├── internal/
│   ├── config/config.go     # YAML config loader
│   ├── hub/hub.go           # WebSocket hub, connection management, broadcast
│   └── metrics/metrics.go   # Prometheus metric definitions
├── example/index.html       # Browser P2P chat demo
├── config.yaml              # Runtime configuration
├── config.example.yaml      # Example config with TLS enabled
└── Makefile                 # Build, test, release commands

License

See repository for license details.