Skip to content

maltemindedal/blip

Repository files navigation

Blip

A small WebSocket broadcast server in Go — one binary, one dependency, no database.

CI Pipeline License: MIT Go Version

Clients connect to /ws, send JSON messages, and every other connected client receives them. That is the whole feature set: no rooms, no history, no accounts. What it does bring is the operational surface you would otherwise write yourself — origin validation against CSWSH, per-connection rate limiting, message size caps, graceful shutdown, and a static cross-platform binary. Use it as a real-time relay behind your own application, or as a starting point to build on.

Quick start

Requires Go 1.26.5 or later (go version) and Git. GNU Make is optional.

git clone https://github.com/maltemindedal/blip.git
cd blip

make build            # or: go build -o bin/blip ./cmd/server
./bin/blip          # Windows: .\bin\blip.exe
time=2026-07-23T15:51:57.081+02:00 level=INFO msg="starting Blip server" version=dev commit=unknown build_time=unknown
time=2026-07-23T15:51:57.081+02:00 level=INFO msg="hub started and ready to manage WebSocket connections"
time=2026-07-23T15:51:57.082+02:00 level=INFO msg="server listening" addr=:8080

Logs are structured key-value records via log/slog; set LOG_LEVEL=debug to trace individual messages.

Open http://localhost:8080/test in two browser tabs, click Connect in each, and type. Messages go to the other tab — senders do not receive their own messages.

With Docker instead:

docker compose up -d --build

Usage

Send and receive JSON with a single content field. The Origin header must match the server's allow-list — browsers set it automatically, other clients must not forget it.

const ws = new WebSocket("ws://localhost:8080/ws");

ws.onopen = () => ws.send(JSON.stringify({ content: "Hello" }));
ws.onmessage = (event) => console.log(JSON.parse(event.data).content);

Configuration is entirely environment variables:

SERVER_PORT=:8080 \
ALLOWED_ORIGINS=http://localhost:8080,http://localhost:3000 \
MAX_MESSAGE_SIZE=512 \
RATE_LIMIT_BURST=5 \
LOG_LEVEL=info \
./bin/blip

Documentation

Full index: docs/README.md.

Guide Contents
Getting started Build, run, and try it in ~10 minutes
Connecting a client JavaScript, Go, Python, websocat examples
Configuration Every environment variable and default
API reference Endpoints, message protocol, failure modes
Deploying to production TLS, reverse proxy, systemd, scaling limits
Security hardening What is protected, and what is not
Architecture overview Hub, client pumps, design trade-offs

Endpoints

Endpoint Purpose
/ws WebSocket endpoint. GET only; rejects disallowed origins with 403
/ Health check returning Blip server is running! (also the catch-all for unmatched paths)
/test Built-in browser test page — development only

Project structure

cmd/server/         Entry point: startup, signal handling, graceful shutdown
internal/server/    Hub, client pumps, handlers, config, origin checks, rate limiter
test/               Unit and integration suites plus shared helpers
docs/               Documentation (see docs/README.md)
.github/workflows/  CI pipeline

Status

Actively maintained, single-instance by design. The hub lives in process memory, so multiple instances behind a load balancer form separate chat rooms — see scaling. There is no built-in authentication; enforce it in front of /ws if your data needs it.

Test coverage was 70.4% of statements as of 2026-07-24 (make test-coverage). Broadcast fan-out and rate limiting are allocation-free per message, and the origin check is allocation-free per handshake — see performance for the numbers and make bench to reproduce them.

Contributing

Bug reports, features, and pull requests are welcome — see docs/contributing.md.

License

MIT — see LICENSE.

About

A fast, in-memory WebSocket broadcast server in Go - one binary, one dependency, no database, allocation-free message fan-out.

Topics

Resources

Contributing

Security policy

Stars

Watchers

Forks

Used by

Contributors

Languages