A robust, lightweight WebSocket server for building real-time applications with features for authorization, broadcasting, and channel management.
- Simple Protocol: Easy-to-understand JSON-based messaging protocol
- Authorization: Webhook-based authorization for connection and message validation
- Multiple Brokers: Support for in-memory and Redis message brokers
- Channel Management: Join, leave, and broadcast to channels
- HTTP Broadcasting: Send messages via HTTP API without WebSocket connection
- Graceful Shutdown: Proper handling of server shutdown for zero downtime deployments
- Health Monitoring: Built-in health check endpoint
- Environment Variable Support: Configure via flags or environment variables
- A WebSocket server should focus on transmitting messages in real-time between connected parties
- Authorization is delegated to an external webhook service
- The protocol should be simple and intuitive
- Resource efficiency and reliability are paramount
A message is a data structure containing commands and arguments:
{
"command": "join",
"args": {
"channel": "some_channel"
}
}Available commands:
join: Join a channel (requires "channel" argument)leave: Leave a channel (requires "channel" argument)broadcast: Send a message to a channel (requires "channel" and "content" arguments)
An optional webhook endpoint that validates connections and messages:
- Responds with HTTP 200 OK to accept a connection or message
- Any other response code rejects the message
- Server error codes (5xx) indicate authorizer unavailability
- Receives all WebSocket messages before processing
- Also validates initial connections with a special "connect" command
Example authorizer request for a connection:
{
"command": "connect",
"args": {
"headers": {...},
"query": {...}
}
}# Clone the repository
git clone https://github.com/ByteBrushStudios/socket0.git
cd socket0
# Build the binary
make build
# Install globally (optional)
make installDownload the appropriate binary for your platform from the Releases page.
# Make the binary executable (Unix-based systems)
chmod +x socket0-linux-amd64
# Move to a directory in your PATH (optional)
sudo mv socket0-linux-amd64 /usr/local/bin/socket0# Pull the image
docker pull ByteBrushStudios/socket0:latest
# Or build locally
make docker-build# Basic usage with memory broker
socket0
# With Redis broker
socket0 --broker-driver redis --broker-dsn redis://localhost:6379
# With authorization webhook
socket0 --authorizer-url http://localhost:8080/authorize
# On a different port
socket0 --listen-addr :8080
# With environment variables
export SOCKET0_BROKER_DRIVER=redis
export SOCKET0_BROKER_DSN=redis://localhost:6379
socket0# Basic usage
docker run -p 3000:3000 ByteBrushStudios/socket0:latest
# With environment variables
docker run -p 3000:3000 \
-e SOCKET0_BROKER_DRIVER=redis \
-e SOCKET0_BROKER_DSN=redis://redis:6379 \
-e SOCKET0_AUTHORIZER_URL=http://auth-service/authorize \
ByteBrushStudios/socket0:latestCreate a docker-compose.yml file:
version: '3'
services:
socket0:
image: ByteBrushStudios/socket0:latest
ports:
- "3000:3000"
environment:
- SOCKET0_BROKER_DRIVER=redis
- SOCKET0_BROKER_DSN=redis://redis:6379
- SOCKET0_AUTHORIZER_URL=http://auth-service/authorize
- SOCKET0_BROADCASTING_KEY=your-secret-key
depends_on:
- redis
redis:
image: redis:alpine
ports:
- "6379:6379"Then run:
docker-compose up// Connect to Socket0
const socket = new WebSocket('ws://localhost:3000/ws');
// Handle connection open
socket.onopen = () => {
console.log('Connected to Socket0');
// Join a channel
socket.send(JSON.stringify({
command: 'join',
args: { channel: 'notifications' }
}));
};
// Handle incoming messages
socket.onmessage = (event) => {
const message = JSON.parse(event.data);
console.log('Received:', message);
};
// Handle errors
socket.onerror = (error) => {
console.error('WebSocket error:', error);
};
// Handle disconnection
socket.onclose = (event) => {
console.log('Disconnected from Socket0', event.code, event.reason);
};
// Broadcast a message
function sendMessage(content) {
socket.send(JSON.stringify({
command: 'broadcast',
args: {
channel: 'notifications',
content: content
}
}));
}
// Leave a channel
function leaveChannel(channel) {
socket.send(JSON.stringify({
command: 'leave',
args: { channel: channel }
}));
}// Node.js example
const axios = require('axios');
async function broadcastMessage(channel, content, broadcastingKey) {
try {
const response = await axios.post(
`http://localhost:3000/broadcast?key=${broadcastingKey}`,
{ channel, content },
{ headers: { 'Content-Type': 'application/json' } }
);
return response.status === 201;
} catch (error) {
console.error('Broadcasting error:', error);
return false;
}
}Socket0 provides a health check endpoint at /health that returns a 200 OK status. You can use this for container health checks:
# Check server health
curl http://localhost:3000/healthHEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1Socket0 includes a comprehensive test suite:
# Run all tests
make test
# Run tests with verbose output
make test-verbose
# Run only unit tests (skip integration tests)
make test-unit
# Run tests with extended timeout (for CI environments)
make test-ciSocket0 uses GitHub Actions for continuous integration and deployment. The workflow:
- Runs the test suite on every push and pull request
- Builds the application to verify it compiles correctly
- Automatically creates releases with binaries for multiple platforms when tags are pushed
You can find the workflow configuration in .github/workflows/go.yml.
# Build for current platform
make build
# Build for multiple platforms
make dist
# Run tests
make test
# Format code
make fmt
# Lint code
make lint
# Install locally
make install
# Install to system location (Linux/macOS)
make install-systemContributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
Run socket0 --help for additional options and information.