2026-01-20 10:03:55 +02:00

89 lines
2.6 KiB
Go

package pubsub
import (
"encoding/base64"
"encoding/json"
"net/http"
"time"
"github.com/DeBrosOfficial/network/pkg/logging"
"github.com/gorilla/websocket"
"go.uber.org/zap"
)
var wsUpgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
// For early development we accept any origin; tighten later.
CheckOrigin: func(r *http.Request) bool { return true },
}
// wsClient wraps a WebSocket connection with message handling
type wsClient struct {
conn *websocket.Conn
topic string
logger *logging.ColoredLogger
}
// newWSClient creates a new WebSocket client wrapper
func newWSClient(conn *websocket.Conn, topic string, logger *logging.ColoredLogger) *wsClient {
return &wsClient{
conn: conn,
topic: topic,
logger: logger,
}
}
// writeMessage sends a message to the WebSocket client with proper envelope formatting
func (c *wsClient) writeMessage(data []byte) error {
c.logger.ComponentInfo("gateway", "pubsub ws: sending message to client",
zap.String("topic", c.topic),
zap.Int("data_len", len(data)))
// Format message as JSON envelope with data (base64 encoded), timestamp, and topic
// This matches the SDK's Message interface: {data: string, timestamp: number, topic: string}
envelope := map[string]interface{}{
"data": base64.StdEncoding.EncodeToString(data),
"timestamp": time.Now().UnixMilli(),
"topic": c.topic,
}
envelopeJSON, err := json.Marshal(envelope)
if err != nil {
c.logger.ComponentWarn("gateway", "pubsub ws: failed to marshal envelope",
zap.String("topic", c.topic),
zap.Error(err))
return err
}
c.logger.ComponentDebug("gateway", "pubsub ws: envelope created",
zap.String("topic", c.topic),
zap.Int("envelope_len", len(envelopeJSON)))
c.conn.SetWriteDeadline(time.Now().Add(30 * time.Second))
if err := c.conn.WriteMessage(websocket.TextMessage, envelopeJSON); err != nil {
c.logger.ComponentWarn("gateway", "pubsub ws: failed to write to websocket",
zap.String("topic", c.topic),
zap.Error(err))
return err
}
c.logger.ComponentInfo("gateway", "pubsub ws: message sent successfully",
zap.String("topic", c.topic))
return nil
}
// writeControl sends a WebSocket control message
func (c *wsClient) writeControl(messageType int, data []byte, deadline time.Time) error {
return c.conn.WriteControl(messageType, data, deadline)
}
// readMessage reads a message from the WebSocket client
func (c *wsClient) readMessage() (messageType int, data []byte, err error) {
return c.conn.ReadMessage()
}
// close closes the WebSocket connection
func (c *wsClient) close() error {
return c.conn.Close()
}