Skip to content

WebSocket System

Base provides powerful WebSocket support for building real-time applications. The /ws endpoint enables bidirectional communication between clients and the server.

WebSocket Features

  • Channel-based Communication: Organize connections into logical channels
  • User Authentication: Secure WebSocket connections with JWT tokens
  • Pub/Sub Pattern: Publish and subscribe to events
  • Broadcast Messages: Send messages to all connected clients
  • Direct Messaging: Send messages to specific clients
  • Room Management: Create and manage rooms for group communication
  • Connection Handling: Manage connections, reconnections, and disconnections

WebSocket Endpoint

MethodEndpointDescriptionQuery Parameters
GET/wsWebSocket connectionchannel: Channel name (optional)
token: JWT token for authentication

WebSocket Example Applications

Base includes several example applications demonstrating WebSocket functionality in the /static directory:

Chat Application

A multi-room chat application that demonstrates:

  • User authentication
  • Room creation and management
  • Real-time messaging
  • User presence
html
<!-- HTML Structure (from chat.html) -->
<div class="container">
    <div class="sidebar">
        <h3>Rooms</h3>
        <ul id="room-list"></ul>
        <input type="text" id="new-room" placeholder="New room name">
        <button id="create-room">Create Room</button>
    </div>
    <div class="main-content">
        <div id="chat-box"></div>
        <div class="input-container">
            <input type="text" id="message-input" placeholder="Type a message...">
            <button id="send-button">Send</button>
        </div>
    </div>
</div>

<!-- JavaScript for WebSocket Connection -->
<script>
let socket;
let currentRoom = 'general';
const nickname = localStorage.getItem('nickname') || 'Guest' + Math.floor(Math.random() * 1000);

function connect() {
    // Close any existing connections
    if (socket) {
        socket.close();
    }

    // Create a new WebSocket connection with the current room
    const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
    const wsUrl = `${wsProtocol}//${window.location.host}/api/ws?channel=${currentRoom}&nickname=${encodeURIComponent(nickname)}`;
    
    socket = new WebSocket(wsUrl);
    
    socket.onopen = function() {
        updateStatus('Connected');
        document.getElementById('connection-status').classList.add('connected');
    };
    
    socket.onclose = function() {
        updateStatus('Disconnected');
        document.getElementById('connection-status').classList.remove('connected');
        
        // Attempt to reconnect after a delay
        setTimeout(connect, 3000);
    };
    
    socket.onerror = function(error) {
        console.error('WebSocket error:', error);
        updateStatus('Error connecting');
    };
    
    socket.onmessage = function(event) {
        const data = JSON.parse(event.data);
        
        if (data.type === 'message') {
            appendMessage(data.content, data.nickname);
        } else if (data.type === 'system') {
            appendMessage(data.content, 'System', true);
        } else if (data.type === 'rooms') {
            // Update room list
            const rooms = data.rooms;
            const roomListEl = document.getElementById('room-list');
            roomListEl.innerHTML = '';
            
            rooms.forEach(room => {
                addRoom(room);
            });
        }
    };
}

function sendMessage(message) {
    if (socket && socket.readyState === WebSocket.OPEN) {
        const data = {
            type: 'message',
            content: message,
            room: currentRoom,
            nickname: nickname
        };
        socket.send(JSON.stringify(data));
        return true;
    }
    return false;
}
</script>

Collaborative Drawing Board

The drawing board demonstrates:

  • Real-time collaboration
  • Event broadcasting
  • Canvas synchronization

Real-time Editor

The collaborative editor shows:

  • Document synchronization
  • Conflict resolution
  • Cursor positioning

Kanban Board

The Kanban board example demonstrates:

  • Drag and drop synchronization
  • State management
  • Real-time updates

System Monitor

The system monitor shows:

  • Server metrics in real-time
  • Time-series data visualization
  • Alerts and notifications

Implementing WebSocket Server-side

On the server side, Base provides a simple API for managing WebSocket connections:

go
// In your module's initialization
import "base/core/ws"

// Create a WebSocket handler
func (m *MyModule) SetupWebSocket() {
    // Create a channel manager
    channelManager := ws.NewChannelManager()
    
    // Register a channel
    chatChannel := channelManager.RegisterChannel("chat")
    
    // Handle new connections
    chatChannel.OnConnect(func(client *ws.Client) {
        // Send welcome message
        client.Send(map[string]interface{}{
            "type": "system",
            "content": "Welcome to the chat!",
        })
        
        // Broadcast join notification
        chatChannel.Broadcast(map[string]interface{}{
            "type": "system",
            "content": client.GetAttr("nickname") + " has joined the chat",
        }, client.ID) // Exclude the joining client
    })
    
    // Handle messages
    chatChannel.OnMessage(func(client *ws.Client, message []byte) {
        // Parse message
        var data map[string]interface{}
        if err := json.Unmarshal(message, &data); err != nil {
            return
        }
        
        // Handle different message types
        switch data["type"].(string) {
        case "message":
            // Add the sender's nickname
            data["nickname"] = client.GetAttr("nickname")
            
            // Broadcast to all clients in the channel
            chatChannel.Broadcast(data, "")
        
        case "private":
            // Send to specific client
            targetClientID := data["target"].(string)
            chatChannel.SendTo(targetClientID, data)
        }
    })
    
    // Handle disconnections
    chatChannel.OnDisconnect(func(client *ws.Client) {
        chatChannel.Broadcast(map[string]interface{}{
            "type": "system",
            "content": client.GetAttr("nickname") + " has left the chat",
        }, "")
    })
}

Combining Media Library and WebSockets

These features can be combined to create powerful interactive applications:

javascript
// Listen for new media uploads via WebSocket
socket.onmessage = function(event) {
    const data = JSON.parse(event.data);
    
    if (data.type === 'new_media') {
        // Add new media item to the gallery without page refresh
        addMediaToGallery(data.media);
    }
};

// Function to add media to gallery
function addMediaToGallery(media) {
    const galleryEl = document.getElementById('media-gallery');
    const mediaEl = document.createElement('div');
    mediaEl.className = 'media-item';
    mediaEl.innerHTML = `
        <img src="${media.url}" alt="${media.title}">
        <h3>${media.title}</h3>
        <p>${media.description || ''}</p>
    `;
    galleryEl.prepend(mediaEl);
}

Collaborative Media Editor

javascript
// When a user edits media metadata
function updateMediaMetadata(mediaId, metadata) {
    // Update via API
    fetch(`/api/media/${mediaId}`, {
        method: 'PUT',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer ' + localStorage.getItem('token')
        },
        body: JSON.stringify(metadata)
    }).then(response => response.json())
      .then(updatedMedia => {
          // Notify other users via WebSocket
          socket.send(JSON.stringify({
              type: 'media_updated',
              mediaId: mediaId,
              metadata: metadata
          }));
      });
}

Released under the MIT License.