gosocket

package module
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 21, 2025 License: MIT Imports: 19 Imported by: 0

README

GoSocket

The simplest way to add WebSockets to your Go application

Go Version GoDoc Go Report Card License

Stop writing WebSocket boilerplate. Start building features.

// That's it. You have a working WebSocket server.
ws, _ := gosocket.NewServer(
    gosocket.WithPort(8080),
    gosocket.OnMessage(func(client *gosocket.Client, message *gosocket.Message, ctx *gosocket.Context) error {
        client.Send(message.RawData) // Echo back
        return nil
    }),
)
log.Fatal(ws.Start())

Why GoSocket?

GoSocket focuses on developer experience and getting started quickly:

  • Minimal boilerplate - Get a WebSocket server running in a few lines
  • Built-in features - Rooms, broadcasting, and client management included
  • Middleware support: Add auth, logging, CORS, whatever you need
  • Simple API - Intuitive methods that do what you expect
  • Flexible - Use standalone or integrate with existing HTTP servers
  • Multiple servers: Run chat, notifications, and admin panels on different ports simultaneously

Quick Start

Installation
go get -u github.com/FilipeJohansson/gosocket@latest
Standalone Server

Perfect for dedicated WebSocket services:

package main

import (
    "fmt"
    "log"
    "github.com/FilipeJohansson/gosocket"
)

func main() {
    ws, err := gosocket.NewServer(
        gosocket.WithPort(8080),
        gosocket.WithPath("/ws"),
        gosocket.OnConnect(func(client *gosocket.Client, ctx *gosocket.Context) error {
            fmt.Printf("Client %s connected\n", client.ID)
            return nil
        }),
        gosocket.OnMessage(func(client *gosocket.Client, message *gosocket.Message, ctx *gosocket.Context) error {
            // Broadcast to all clients
            ctx.Hub().BroadcastMessage(gosocket.NewRawMessage(gosocket.TextMessage, message.RawData))
            return nil
        }),
        gosocket.OnDisconnect(func(client *gosocket.Client, ctx *gosocket.Context) error {
            fmt.Printf("Client %s disconnected\n", client.ID)
            return nil
        }),
    )

    if err != nil {
        // Something wrong with the server configuration
    }
    
    log.Fatal(ws.Start())
}
Integrate with Existing HTTP Server

Perfect for adding real-time features to REST APIs:

package main

import (
    "net/http"
    "github.com/FilipeJohansson/gosocket"
)

func main() {
    // Your existing routes
    http.HandleFunc("/api/users", getUsersHandler)
    
    // Add WebSocket endpoint
    ws, err := gosocket.NewHandler(
        gosocket.OnMessage(func(client *gosocket.Client, message *gosocket.Message, ctx *gosocket.Context) error {
            client.Send(message.RawData)
            return nil
        }),
    )

    if err != nil {
        // Something wrong with the handler configuration
    }
    
    http.Handle("/ws", ws)
    http.ListenAndServe(":8080", nil)
}

Middleware Support

Add authentication, logging, CORS, and more:

ws, _ := gosocket.NewServer(
    gosocket.WithPort(8080),
    gosocket.WithAuth(AuthMiddleware),
    gosocket.WithMiddleware(LoggingMiddleware),
    gosocket.OnConnect(func(client *gosocket.Client, ctx *gosocket.Context) error {
        fmt.Printf("Authenticated client connected: %s\n", client.ID)
        return nil
    }),
)

Rooms & Broadcasting

gosocket.OnConnect(func(client *gosocket.Client, ctx *gosocket.Context) error {
    client.JoinRoom("general")
    return nil
})

gosocket.OnMessage(func(client *gosocket.Client, message *gosocket.Message, ctx *gosocket.Context) error {
    // Send to specific room
    ctx.Hub().BroadcastToRoom("general", gosocket.NewRawMessage(gosocket.TextMessage, message.RawData))
    
    // Send to specific client
    client.Send([]byte("ACK"))
    
    // Send to everyone
    ctx.Hub().BroadcastMessage(gosocket.NewRawMessage(gosocket.TextMessage, []byte("Global announcement")))
    
    return nil
})

Real-World Examples

Features

  • Quick Setup - Minimal code to get started
  • Built-in Rooms - Join/leave rooms without manual management
  • Broadcasting - Send to all clients, rooms, or individuals
  • Flexible Integration - Standalone server or HTTP handler
  • Multiple Encodings - JSON ready, Protobuf & MessagePack coming

Roadmap to v1.0.0

Status Feature
✅ Completed WebSocket server + middleware
✅ Completed Rooms and broadcasting
🔄 In Progress Rate limiting, logging and other improvements
⚪ Planned Protobuf & MessagePack support
⚪ Planned Clustering & high availability
⚪ Planned Monitoring & metrics
⚪ Planned Performance benchmarks

Note: These are the key steps we need to complete before GoSocket reaches v1.0.0. Once all planned features are implemented and thoroughly tested, we aim to release the first stable version.

Contributing

We're actively looking for contributors! Areas where you can help:

  • Documentation: Improve examples and guides
  • Testing: Write tests and benchmarks
  • Features: Help implement features listed in the roadmap section
  • Bug fixes: Report and fix issues

Check out CONTRIBUTING.md to get started.

License

MIT License - see LICENSE for details.


Love GoSocket? Give us a ⭐ and help spread the word!

🐦 Tweet📺 Demo💬 Discussions

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// Server/Handler configuration errors
	ErrMaxConnectionsLessThanOne = errors.New("max connections must be greater than 0")
	ErrMessageSizeLessThanOne    = errors.New("message size must be greater than 0")
	ErrTimeoutsLessThanOne       = errors.New("read and write timeouts must be greater than 0")
	ErrPingPongLessThanOne       = errors.New("ping and pong wait periods must be greater than 0")
	ErrPongWaitLessThanPing      = errors.New("pong wait must be greater than ping period")
	ErrSSLFilesEmpty             = errors.New("certFile or keyFile is empty")
	ErrWithOnlyServer            = errors.New("can only be set on server")
	ErrInvalidPort               = errors.New("invalid port")
	ErrDepthLessThanOne          = errors.New("depth must be greater than 0")
	ErrMaxKeyLengthLessThanOne   = errors.New("max key length must be greater than 0")
	ErrMaxElementsLessThanOne    = errors.New("max elements must be greater than 0")
	ErrMaxBinarySizeLessThanOne  = errors.New("max binary size must be greater than 0")

	// Client errors
	ErrClientConnNil  = errors.New("client connection is nil")
	ErrNoDataToSend   = errors.New("message has no data to send")
	ErrClientFull     = errors.New("client message channel is full")
	ErrClientNotFound = errors.New("client not found")

	// Server errors
	ErrServerAlreadyRunning = errors.New("server is already running")
	ErrServerNotRunning     = errors.New("server is not running")
	ErrServerNotInitialized = errors.New("server not properly initialized")
	ErrServerStopped        = errors.New("server stopped with error")
	ErrServerShutdown       = errors.New("server shutdown")

	// Handler errors
	ErrSetWriteDeadline  = errors.New("failed to set write deadline")
	ErrSetReadDeadline   = errors.New("failed to set read deadline")
	ErrSendMessage       = errors.New("failed to send message")
	ErrEventFailed       = errors.New("event failed")
	ErrAuthFailure       = errors.New("authentication failed")
	ErrTooManyRequests   = errors.New("too many requests")
	ErrRateLimitExceeded = errors.New("rate limit exceeded")

	// Hub errors
	ErrHubIsNil      = errors.New("hub is nil")
	ErrUpgradeFailed = errors.New("websocket upgrade failed")

	// Room errors
	ErrRoomNameEmpty     = errors.New("room name cannot be empty")
	ErrRoomNotFound      = errors.New("room not found")
	ErrRoomAlreadyExists = errors.New("room already exists")

	// Serializer errors
	ErrRawSerializer           = errors.New("raw serializer expects []byte")
	ErrRawSerializerPtr        = errors.New("raw serializer expects *[]byte")
	ErrSerializeData           = errors.New("failed to serialize data")
	ErrSerializerNotFound      = errors.New("serializer not found for encoding")
	ErrMaxDepthExceeded        = errors.New("max depth exceeded")
	ErrMaxKeyLengthExceeded    = errors.New("max key length exceeded")
	ErrMaxElementsExceeded     = errors.New("max elements exceeded")
	ErrMaxStringLengthExceeded = errors.New("max string length exceeded")
	ErrTypeNotAllowed          = errors.New("type not allowed")
	ErroInvalidValue           = errors.New("invalid value")
	ErrEmptyData               = errors.New("empty data")
	ErrDataTooLong             = errors.New("data too long")
	ErrInvalidJSON             = errors.New("invalid JSON")
	ErrInvalidStruct           = errors.New("invalid struct")

	// Connection Pool errors
	ErrMaxConnReached      = errors.New("max connections reached")
	ErrMaxConnPerIpReached = errors.New("max connections per IP reached")

	// Encoding errors
	ErrRawEncoding         = errors.New("raw encoding expects []byte data")
	ErrUnsupportedEncoding = errors.New("unsupported encoding")
)

Functions

func GenerateClientID added in v0.3.0

func GenerateClientID() string

Types

type AuthFunc

type AuthFunc func(*http.Request) (map[string]interface{}, error)

type BaseSerializer added in v0.4.0

type BaseSerializer struct {
	Config SerializationConfig
}

func NewBaseSerializer added in v0.4.0

func NewBaseSerializer(config SerializationConfig) BaseSerializer

func (*BaseSerializer) Configure added in v0.4.0

func (b *BaseSerializer) Configure(config SerializationConfig)

func (*BaseSerializer) ValidateType added in v0.4.0

func (b *BaseSerializer) ValidateType(t reflect.Type, depth int) error

func (*BaseSerializer) ValidateValue added in v0.4.0

func (b *BaseSerializer) ValidateValue(v interface{}, depth int) error

type Client

type Client struct {
	ID          string
	Conn        IWebSocketConn // WebSocket connection (gorilla/websocket.Conn)
	MessageChan chan []byte
	Hub         IHub
	UserData    map[string]interface{} // user custom data
	ConnInfo    *ConnectionInfo
	// contains filtered or unexported fields
}

func NewClient

func NewClient(id string, conn IWebSocketConn, hub IHub, messageChanBufSize int) *Client

NewClient creates a new Client instance.

The id parameter should be a unique identifier for the client. The conn parameter should be a WebSocket connection. The hub parameter should be the Hub to which the client belongs.

The created Client instance will have a message channel with a capacity of 256. The channel will receive messages from the underlying WebSocket connection.

The created Client instance will also have a map to store user custom data. The map will be empty initially.

func (*Client) Disconnect

func (c *Client) Disconnect() error

Disconnect removes the client from its hub and closes its connection. It will return nil if the client is not connected to a hub or if the connection is nil. Otherwise, it will return the error from closing the connection.

This method is safe to call concurrently.

func (*Client) GetRooms

func (c *Client) GetRooms() []string

GetRooms returns the rooms the client is currently in. If the client's hub is nil, it will return an empty slice. Otherwise, it will return the names of the rooms the client is in.

This method is safe to call concurrently.

func (*Client) GetUserData

func (c *Client) GetUserData(key string) interface{}

GetUserData gets a value from the client's user data map by its key.

This method is safe to call concurrently.

func (*Client) IsConnected added in v0.4.0

func (c *Client) IsConnected() bool

func (*Client) JoinRoom

func (c *Client) JoinRoom(roomName string) error

JoinRoom joins the given room. It will return an error if the client's hub is nil. Otherwise, it will call the hub's JoinRoom method with the client and room.

This method is safe to call concurrently.

func (*Client) LeaveRoom

func (c *Client) LeaveRoom(room string) error

LeaveRoom leaves the given room. It will return an error if the client's hub is nil. Otherwise, it will call the hub's LeaveRoom method with the client and room.

This method is safe to call concurrently.

func (*Client) Send

func (c *Client) Send(message []byte) error

Send sends a message to the client. It will send the message if the message channel is not full. If the channel is full, it will return an error.

This method is safe to call concurrently.

func (*Client) SendData

func (c *Client) SendData(data interface{}) error

SendData sends the given data to the client. It will be sent as JSON if no encoding type is specified.

This method is safe to call concurrently.

func (*Client) SendDataWithEncoding

func (c *Client) SendDataWithEncoding(data interface{}, encoding EncodingType) error

SendDataWithEncoding sends the given data to the client using the specified encoding type.

If the encoding type is JSON, it will be sent as JSON. If the encoding type is Raw, it will be sent directly as a byte slice. If the data is not a byte slice, an error will be returned.

If the encoding type is not supported, an error will be returned.

This method is safe to call concurrently.

func (*Client) SendJSON

func (c *Client) SendJSON(data interface{}) error

SendJSON sends the given data to the client as JSON.

It will marshal the given data to JSON and send it to the client. If the marshaling fails, an error will be returned.

The given data must be a valid JSON structure.

This method is safe to call concurrently.

func (*Client) SendMessage

func (c *Client) SendMessage(message *Message) error

SendMessage sends a message to the client.

If the message has a RawData field that is not nil, it will be sent directly. Otherwise, the Data field will be sent with the Encoding specified in the message. If the Encoding field is 0, it will be assumed to be JSON.

The SendJSON and Send methods will be used to send the message.

If the message has no data to send, an error will be returned.

This method is safe to call concurrently.

func (*Client) SendProtobuf

func (c *Client) SendProtobuf(data interface{}) error

SendProtobuf sends the given data to the client as a Protobuf message.

Currently, this is not implemented and will return an error.

This method is safe to call concurrently.

TODO: implement

func (*Client) SetUserData

func (c *Client) SetUserData(key string, value interface{})

SetUserData sets a value for a key in the client's user data map.

This method is safe to call concurrently.

type ConnectionInfo added in v0.2.0

type ConnectionInfo struct {
	ClientIP  string
	UserAgent string
	Origin    string
	Headers   map[string]string
	RequestID string
}

type ConnectionPool added in v0.4.0

type ConnectionPool struct {
	// contains filtered or unexported fields
}

func NewConnectionPool added in v0.4.0

func NewConnectionPool(maxTotal, maxPerIP int) *ConnectionPool

func (*ConnectionPool) AcquireConnection added in v0.4.0

func (cp *ConnectionPool) AcquireConnection(clientIP string) error

func (*ConnectionPool) GetStats added in v0.4.0

func (cp *ConnectionPool) GetStats() (total int, perIP map[string]int)

func (*ConnectionPool) ReleaseConnection added in v0.4.0

func (cp *ConnectionPool) ReleaseConnection(clientIP string)

type Context added in v0.4.0

type Context struct {
	// contains filtered or unexported fields
}

func NewHandlerContext added in v0.2.0

func NewHandlerContext(handler *Handler) *Context

NewHandlerContext creates a new context (for inner goroutines) It creates a new context with the given handler and hub, and the same connection info as the original context. The context is created with a new background context, and the start time is set to the current time.

func NewHandlerContextFromRequest added in v0.2.0

func NewHandlerContextFromRequest(handler *Handler, r *http.Request) *Context

NewHandlerContextFromRequest creates a new context from the given http request. It retrieves the client IP, user agent, origin, and headers from the request and uses them to create a new context.

func (*Context) Cancel added in v0.4.0

func (hc *Context) Cancel()

Cancel cancels the context associated with the handler context. If the context is cancelled, any blocked calls to the context's Done method will return immediately. If the context is already cancelled, this method does nothing. The context is cancelled regardless of whether the handler context is associated with a connection or not.

func (*Context) ClientIP added in v0.4.0

func (hc *Context) ClientIP() string

ClientIP returns the client IP address associated with the context. If the context is not associated with a connection, "unknown" is returned.

func (*Context) Context added in v0.4.0

func (hc *Context) Context() context.Context

Context returns the context associated with the handler context. The context is the parent context that was passed when creating the handler context. The context can be used to cancel the context, or to retrieve values from the context.

func (*Context) Handler added in v0.4.0

func (hc *Context) Handler() *Handler

Handler returns the handler associated with the context. This can be used to access the underlying handler's configuration and functionality.

func (*Context) Header added in v0.4.0

func (hc *Context) Header(key string) string

Header returns the value of the given header key associated with the context. If the context is not associated with a connection, an empty string is returned.

func (*Context) Headers added in v0.4.0

func (hc *Context) Headers() map[string]string

Headers returns the HTTP headers associated with the context. If the context is not associated with a connection, nil is returned.

func (*Context) Hub added in v0.4.0

func (hc *Context) Hub() IHub

Hub returns the hub associated with the context. This can be used to access the hub's methods and configuration. The returned hub is the same as the one passed when creating the HandlerContext. If the context is not associated with a hub, nil is returned.

This method is safe to call concurrently.

func (*Context) Origin added in v0.4.0

func (hc *Context) Origin() string

Origin returns the origin associated with the context. The origin is the value of the Origin header of the request that established the connection. If the context is not associated with a connection, an empty string is returned.

func (*Context) ProcessingDuration added in v0.4.0

func (hc *Context) ProcessingDuration() time.Duration

ProcessingDuration returns the time elapsed since the context was created. The returned duration is the time elapsed between the context creation time and the current time. If the context is not associated with a connection, 0 is returned.

func (*Context) RequestID added in v0.4.0

func (hc *Context) RequestID() string

RequestID returns the request ID associated with the context. The request ID is a unique identifier for the connection, and can be used to identify the connection in logs and metrics. If the context is not associated with a connection, an empty string is returned.

func (*Context) UserAgent added in v0.4.0

func (hc *Context) UserAgent() string

UserAgent returns the user agent associated with the context. If the context is not associated with a connection, an empty string is returned.

func (*Context) WithContext added in v0.4.0

func (hc *Context) WithContext(ctx context.Context) *Context

WithContext returns a new context with the given context. The context is the parent context that was passed when creating the handler context. The context can be used to cancel the context, or to retrieve values from the context. The new context is a shallow copy of the original context, with the context replaced.

func (*Context) WithTimeout added in v0.4.0

func (hc *Context) WithTimeout(timeout time.Duration) (*Context, context.CancelFunc)

WithTimeout returns a new context with the given timeout, and a cancel function. The returned context is a shallow copy of the original context, with the timeout set to the given value. The cancel function can be used to cancel the context, or to retrieve values from the context. The context can be used to cancel the context, or to retrieve values from the context.

type DefaultLogger added in v0.4.0

type DefaultLogger struct{}

func (*DefaultLogger) Log added in v0.4.0

func (l *DefaultLogger) Log(logType LogType, level LogLevel, msg string, args ...interface{})

type EncodingType

type EncodingType int
const (
	JSON EncodingType = iota
	Protobuf
	MessagePack
	CBOR
	Raw // to raw binary data
)

type Events added in v0.3.0

type Events struct {
	OnBeforeConnect   OnBeforeConnectFunc
	OnConnect         OnConnectFunc
	OnDisconnect      OnDisconnectFunc
	OnMessage         OnMessageFunc
	OnRawMessage      OnRawMessageFunc
	OnJSONMessage     OnJSONMessageFunc
	OnProtobufMessage OnProtobufMessageFunc
	OnError           OnErrorFunc
	OnPing            OnPingFunc
	OnPong            OnPongFunc
}

type Handler

type Handler struct {
	// contains filtered or unexported fields
}

func NewHandler

func NewHandler(options ...UniversalOption) (*Handler, error)

NewHandler returns a new instance of Handler with default configuration. The default configuration is to accept up to 1000 connections and to set the read and write buffers to 1024 bytes. The default encoding is JSON, but you can change it by calling the WithEncoding method.

func (*Handler) AddSerializer added in v0.3.0

func (h *Handler) AddSerializer(encoding EncodingType, serializer Serializer)

func (*Handler) ApplyMiddlewares

func (h *Handler) ApplyMiddlewares(handler http.Handler) http.Handler

ApplyMiddlewares applies all configured middlewares to the given handler. The middlewares are applied in reverse order of how they were added to the handler. If no middlewares are configured, the original handler is returned.

func (*Handler) AuthFunc added in v0.3.0

func (h *Handler) AuthFunc() AuthFunc

func (*Handler) Config added in v0.3.0

func (h *Handler) Config() HandlerConfig

func (*Handler) GetConnectionStats added in v0.4.0

func (h *Handler) GetConnectionStats() (int, map[string]int)

func (*Handler) HandleWebSocket added in v0.2.0

func (h *Handler) HandleWebSocket(w http.ResponseWriter, r *http.Request)

HandleWebSocket is the HTTP handler that is registered for the WebSocket endpoint. It upgrades the connection to a WebSocket connection, authenticates the user using the authFunc, and then adds the client to the hub and starts the client's read and write goroutines. It also calls the OnConnect handler if it is set.

This method is safe to call concurrently.

func (*Handler) Handler added in v0.3.0

func (h *Handler) Handler() *Handler

func (*Handler) Handlers added in v0.3.0

func (h *Handler) Handlers() *Events

func (*Handler) Hub added in v0.3.0

func (h *Handler) Hub() IHub

func (*Handler) Middlewares added in v0.3.0

func (h *Handler) Middlewares() []Middleware

func (*Handler) Serializers added in v0.3.0

func (h *Handler) Serializers() map[EncodingType]Serializer

func (*Handler) ServeHTTP

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements the http.Handler interface. It is the entrypoint for handling all WebSocket requests. It first ensures that the hub is running, and then applies all configured middlewares to the request. Finally, it calls the configured WebSocket handler.

func (*Handler) SetDefaultEncoding added in v0.3.0

func (h *Handler) SetDefaultEncoding(encoding EncodingType)

func (*Handler) SetHub added in v0.3.0

func (h *Handler) SetHub(hub IHub)

type HandlerConfig

type HandlerConfig struct {
	MaxConnections      int
	MaxConnectionsPerIP int
	MessageChanBufSize  int
	MessageSize         int64
	ReadTimeout         time.Duration
	WriteTimeout        time.Duration
	PingPeriod          time.Duration
	PongWait            time.Duration
	ConnectionTimeout   time.Duration
	AllowedOrigins      []string
	RelevantHeaders     []string
	DefaultEncoding     EncodingType // default message encoding
	Serialization       SerializationConfig
}

func DefaultHandlerConfig

func DefaultHandlerConfig() *HandlerConfig

type HasHandler added in v0.3.0

type HasHandler interface {
	Handler() *Handler
}

type Hub

type Hub struct {
	Clients    *SharedCollection[*Client]
	Rooms      *SharedCollection[*Room]
	Register   chan *Client
	Unregister chan *Client
	Broadcast  chan *Message
	// contains filtered or unexported fields
}

func NewHub

func NewHub(logger *LoggerConfig) *Hub

NewHub creates a new Hub instance. It returns a pointer to a Hub struct.

The created Hub instance will have empty maps for the clients and rooms. The Register, Unregister and Broadcast channels will be created with a default buffer size.

func (*Hub) AddClient

func (h *Hub) AddClient(client *Client)

AddClient adds a client to the hub, and broadcasts the client to all other clients. It does not return an error, even if the client is already in the hub.

func (*Hub) BroadcastMessage

func (h *Hub) BroadcastMessage(message *Message)

BroadcastMessage broadcasts a message to all clients in the hub.

It is a shorthand for calling Broadcast(h, message).

func (*Hub) BroadcastToRoom

func (h *Hub) BroadcastToRoom(roomName string, message *Message)

BroadcastToRoom broadcasts a message to all clients in the given room.

It returns an error if the room does not exist.

It is a shorthand for calling Broadcast(h, message) after getting the clients from the room.

func (*Hub) CreateRoom

func (h *Hub) CreateRoom(ownerId, roomName string) (*Room, error)

CreateRoom creates a new room with the given name. If the room already exists, the method will return nil. If the name is empty, an error is returned.

This method is safe to call concurrently.

func (*Hub) DeleteRoom

func (h *Hub) DeleteRoom(roomName string) error

DeleteRoom deletes a room with the given name. If the room does not exist, it will return an error. If the room exists, it will remove all clients from the room and remove the room from the hub.

This method is safe to call concurrently.

func (*Hub) GetClients

func (h *Hub) GetClients() []*Client

GetClients returns a copy of the clients map, where the keys are the client pointers and the values are booleans indicating whether the client is connected to the hub.

This method is safe to call concurrently.

func (*Hub) GetRoom added in v0.5.0

func (h *Hub) GetRoom(roomName string) *Room

GetRoom returns the room with the given name. If the room does not exist, nil is returned.

This method is safe to call concurrently.

func (*Hub) GetRoomClients

func (h *Hub) GetRoomClients(roomName string) []*Client

GetRoomClients returns all clients in the specified room. If the room does not exist, an empty slice is returned.

This method is safe to call concurrently.

func (*Hub) GetRooms

func (h *Hub) GetRooms() []*Room

GetRooms returns a copy of the rooms map, where the keys are the room names and the values are maps with client pointers as keys and booleans indicating whether the client is connected to the room.

This method is safe to call concurrently.

func (*Hub) GetStats

func (h *Hub) GetStats() map[string]interface{}

GetStats returns a map with the following keys:

- total_clients: The total number of clients connected to the hub. - total_rooms: The total number of rooms in the hub. - rooms: A map with room names as keys and the number of clients in each room as values.

This method is safe to call concurrently.

func (*Hub) IsRunning

func (h *Hub) IsRunning() bool

IsRunning returns a boolean indicating whether the hub is currently running.

This method is safe to call concurrently.

func (*Hub) JoinRoom

func (h *Hub) JoinRoom(client *Client, roomName string)

JoinRoom adds a client to a room. If the room does not exist, it is created.

This method is safe to call concurrently.

func (*Hub) LeaveRoom

func (h *Hub) LeaveRoom(client *Client, roomName string)

LeaveRoom removes the given client from the given room. If the room does not exist, or if the client is not in the room, the method does nothing.

This method is safe to call concurrently.

func (*Hub) Log added in v0.4.0

func (h *Hub) Log(logType LogType, level LogLevel, msg string, args ...interface{})

func (*Hub) RemoveClient

func (h *Hub) RemoveClient(client *Client)

RemoveClient removes a client from the hub and closes the client's message channel. It does not return an error, even if the client is not in the hub.

func (*Hub) Run

func (h *Hub) Run(ctx context.Context)

Run starts the hub. It is a blocking call and will run until the Stop method is called.

It handles the following events: - Register: adds a client to the hub and broadcasts the client to all other clients - Unregister: removes a client from the hub, closes the client's message channel and removes the client from all rooms - Broadcast: broadcasts a message to all clients in the hub

func (*Hub) Stop

func (h *Hub) Stop()

Stop stops the hub. It is a blocking call and will not return until the hub is fully stopped.

It will close the message channel of all clients and reset the hub's state.

The Stop method is safe to call concurrently.

type IClient

type IClient interface {
	// Send sends a raw byte message to the server.
	// The message is sent as-is, without any encoding or processing.
	Send(message []byte) error

	// SendMessage sends a message to the server, with the option to specify encoding.
	// The message is sent with the specified encoding, if any.
	SendMessage(message *Message) error

	// SendData sends arbitrary data to the server, automatically encoding it as JSON.
	// The data is marshaled to JSON and sent to the server.
	SendData(data interface{}) error

	// SendDataWithEncoding sends arbitrary data to the server with a specified encoding.
	// The data is marshaled to the specified encoding and sent to the server.
	SendDataWithEncoding(data interface{}, encoding EncodingType) error

	// SendJSON sends JSON-encoded data to the server.
	// The data is marshaled to JSON and sent to the server.
	SendJSON(data interface{}) error

	// SendProtobuf sends Protobuf-encoded data to the server.
	// The data is marshaled to Protobuf and sent to the server.
	SendProtobuf(data interface{}) error

	// JoinRoom joins a specific room on the server.
	// The client becomes a member of the specified room.
	JoinRoom(room string) error

	// LeaveRoom leaves a specific room on the server.
	// The client is removed from the specified room.
	LeaveRoom(room string) error

	// GetRooms retrieves a list of rooms the client is currently in.
	// The list of rooms is returned as a slice of strings.
	GetRooms() []string

	// Disconnect disconnects the client from the server.
	// The client's connection to the server is closed.
	Disconnect() error

	// IsConnected checks if the client is currently connected to the server.
	IsConnected() bool

	// SetUserData sets arbitrary user data associated with the client.
	// The data is stored on the client and can be retrieved later.
	SetUserData(key string, value interface{})

	// GetUserData retrieves arbitrary user data associated with the client.
	// The data is returned as an interface{} value.
	GetUserData(key string) interface{}
}

IClient is an interface for a client in a WebSocket application. It defines the methods that a client must implement to interact with the server.

type IHub

type IHub interface {
	// Run starts the hub.
	Run(ctx context.Context)

	// Stop stops the hub.
	Stop()

	// AddClient adds a client to the hub.
	AddClient(client *Client)

	// RemoveClient removes a client from the hub.
	RemoveClient(client *Client)

	// BroadcastMessage sends a message to all connected clients.
	BroadcastMessage(message *Message)

	// BroadcastToRoom sends a message to all clients in a specific room.
	BroadcastToRoom(roomName string, message *Message)

	// CreateRoom creates a new room with the given name.
	CreateRoom(ownerId, roomName string) (*Room, error)

	// JoinRoom adds a client to a room.
	JoinRoom(client *Client, roomName string)

	// LeaveRoom removes a client from a room.
	LeaveRoom(client *Client, roomName string)

	// GetRoomClients returns a list of clients in a room.
	GetRoomClients(roomName string) []*Client

	// GetStats returns statistics about the hub.
	GetStats() map[string]interface{}

	// GetClients returns a list of all connected clients.
	GetClients() []*Client

	// GetRooms returns a list of all rooms.
	GetRooms() []*Room

	// GetRoom returns a room with the given name.
	GetRoom(roomName string) *Room

	// DeleteRoom deletes a room with the given name.
	DeleteRoom(roomName string) error

	// IsRunning returns whether the hub is currently running.
	IsRunning() bool

	Log(logType LogType, level LogLevel, msg string, args ...interface{})
}

IHub is an interface for a hub that manages client connections and rooms.

It provides methods for running and stopping the hub, managing clients and rooms, broadcasting messages, and retrieving statistics and client information.

type IServer

type IServer interface {
	// Start starts the server.
	Start() error

	// StartWithContext starts the server with the given context.
	StartWithContext(ctx context.Context) error

	// Stop stops the server.
	Stop() error

	// StopGracefully stops the server gracefully with the given timeout.
	StopGracefully(timeout time.Duration) error

	// Broadcast sends a message to all connected clients.
	Broadcast(message []byte) error

	// BroadcastMessage sends a message to all connected clients.
	BroadcastMessage(message *Message) error

	// BroadcastData sends data to all connected clients.
	BroadcastData(data interface{}) error

	// BroadcastDataWithEncoding sends data to all connected clients with the given encoding.
	BroadcastDataWithEncoding(data interface{}, encoding EncodingType) error

	// BroadcastJSON sends JSON data to all connected clients.
	BroadcastJSON(data interface{}) error

	// BroadcastProtobuf sends Protobuf data to all connected clients.
	BroadcastProtobuf(data interface{}) error

	// BroadcastToRoom sends a message to all clients in the given room.
	BroadcastToRoom(room string, message []byte) error

	// BroadcastToRoomData sends data to all clients in the given room.
	BroadcastToRoomData(room string, data interface{}) error

	// BroadcastToRoomJSON sends JSON data to all clients in the given room.
	BroadcastToRoomJSON(room string, data interface{}) error

	// BroadcastToRoomProtobuf sends Protobuf data to all clients in the given room.
	BroadcastToRoomProtobuf(room string, data interface{}) error

	// GetClients returns a list of all connected clients.
	GetClients() []*Client

	// GetClient returns the client with the given ID.
	GetClient(id string) *Client

	// GetClientsInRoom returns a list of all clients in the given room.
	GetClientsInRoom(room string) []*Client

	// GetClientCount returns the number of connected clients.
	GetClientCount() int

	// DisconnectClient disconnects the client with the given ID.
	DisconnectClient(id string) error

	// CreateRoom creates a new room with the given name.
	CreateRoom(name string) error

	// DeleteRoom deletes the room with the given name.
	DeleteRoom(name string) error

	// GetRooms returns a list of all rooms.
	GetRooms() []string

	// JoinRoom joins the client with the given ID to the room with the given name.
	JoinRoom(clientID, room string) error

	// LeaveRoom leaves the client with the given ID from the room with the given name.
	LeaveRoom(clientID, room string) error
}

IServer defines the interface for a server that can manage client connections, broadcast messages, and handle various events.

type IWebSocketConn

type IWebSocketConn interface {
	Close() error
	WriteMessage(messageType int, data []byte) error
	ReadMessage() (messageType int, p []byte, err error)
}

type JSONSerializer

type JSONSerializer struct {
	BaseSerializer
}

func NewJSONSerializer added in v0.4.0

func NewJSONSerializer(config SerializationConfig) *JSONSerializer

func (*JSONSerializer) ContentType

func (j *JSONSerializer) ContentType() string

func (*JSONSerializer) EncodingType

func (j *JSONSerializer) EncodingType() EncodingType

func (*JSONSerializer) Marshal

func (j *JSONSerializer) Marshal(v interface{}) ([]byte, error)

func (*JSONSerializer) Unmarshal

func (j *JSONSerializer) Unmarshal(data []byte, v interface{}) error

type LogLevel added in v0.4.0

type LogLevel int
const (
	LogLevelNone LogLevel = iota
	LogLevelError
	LogLevelWarn
	LogLevelInfo
	LogLevelDebug
)

type LogType added in v0.4.0

type LogType string
const (
	LogTypeServer     LogType = "server"     // for server events
	LogTypeClient     LogType = "client"     // for client events
	LogTypeAuth       LogType = "auth"       // for auth events
	LogTypeBroadcast  LogType = "broadcast"  // for messages sent to multiple clients/rooms
	LogTypeConnection LogType = "connection" // for connection events
	LogTypeMessage    LogType = "message"    // for messages sent and received
	LogTypeError      LogType = "error"      // for internal errors and connection errors
	LogTypeRateLimit  LogType = "ratelimit"  // for rate limit events
	LogTypeOther      LogType = "other"      // generic
)

type Logger added in v0.4.0

type Logger interface {
	Log(logType LogType, level LogLevel, msg string, args ...interface{})
}

type LoggerConfig added in v0.4.0

type LoggerConfig struct {
	Logger Logger
	Level  map[LogType]LogLevel
}

func DefaultLoggerConfig added in v0.4.0

func DefaultLoggerConfig() *LoggerConfig

type Message

type Message struct {
	Type     MessageType  `json:"type"`
	Data     interface{}  `json:"data"`     // original data (struct, map, etc)
	RawData  []byte       `json:"raw_data"` // serialized data
	Encoding EncodingType `json:"encoding"` // used encoding type
	From     string       `json:"from,omitempty"`
	To       string       `json:"to,omitempty"`
	Room     string       `json:"room,omitempty"`
	Created  time.Time    `json:"created"`
}

generic WebSocket message

func NewMessage

func NewMessage(msgType MessageType, data interface{}) *Message

NewMessage creates a new Message with the given MessageType and data.

The data must be a valid JSON structure, and will be serialized to a byte slice. If the data is not a valid JSON structure, an error will be returned.

The Encoding field of the Message will be set to JSON.

func NewMessageWithEncoding

func NewMessageWithEncoding(msgType MessageType, data interface{}, encoding EncodingType) *Message

NewMessageWithEncoding creates a new Message with the given MessageType, data, and Encoding type.

The data must be a valid JSON structure, and will be serialized to a byte slice. If the data is not a valid JSON structure, an error will be returned.

The Encoding field of the Message will be set to the provided Encoding type.

func NewRawMessage

func NewRawMessage(msgType MessageType, rawData []byte) *Message

NewRawMessage creates a new Message with the given MessageType and raw data.

The RawData field of the Message will be set to the provided raw data. The Encoding field of the Message will be set to Raw.

type MessageType

type MessageType int
const (
	TextMessage MessageType = iota
	BinaryMessage
	PingMessage
	PongMessage
	CloseMessage
)

type Middleware

type Middleware func(http.Handler) http.Handler

type NullLogger added in v0.4.0

type NullLogger struct{}

func (*NullLogger) Log added in v0.4.0

func (l *NullLogger) Log(logType LogType, level LogLevel, msg string, args ...interface{})

type OnBeforeConnectFunc added in v0.4.0

type OnBeforeConnectFunc func(r *http.Request, ctx *Context) error

type OnConnectFunc added in v0.3.0

type OnConnectFunc func(c *Client, ctx *Context) error

type OnDisconnectFunc added in v0.3.0

type OnDisconnectFunc func(c *Client, ctx *Context) error

type OnErrorFunc added in v0.3.0

type OnErrorFunc func(c *Client, err error, ctx *Context) error

type OnJSONMessageFunc added in v0.3.0

type OnJSONMessageFunc func(c *Client, m interface{}, ctx *Context) error // JSON specific handler

type OnMessageFunc added in v0.3.0

type OnMessageFunc func(c *Client, m *Message, ctx *Context) error // generic handler

type OnPingFunc added in v0.3.0

type OnPingFunc func(c *Client, ctx *Context) error

type OnPongFunc added in v0.3.0

type OnPongFunc func(c *Client, ctx *Context) error

type OnProtobufMessageFunc added in v0.3.0

type OnProtobufMessageFunc func(c *Client, m interface{}, ctx *Context) error // Protobuf specific handler

type OnRawMessageFunc added in v0.3.0

type OnRawMessageFunc func(c *Client, m []byte, ctx *Context) error // raw data handler

type ProtobufSerializer

type ProtobufSerializer struct {
	BaseSerializer
}

ProtobufSerializer default Protobuf implementation

func NewProtobufSerializer added in v0.4.0

func NewProtobufSerializer(config SerializationConfig) *ProtobufSerializer

func (*ProtobufSerializer) ContentType

func (p *ProtobufSerializer) ContentType() string

func (*ProtobufSerializer) EncodingType

func (p *ProtobufSerializer) EncodingType() EncodingType

func (*ProtobufSerializer) Marshal

func (p *ProtobufSerializer) Marshal(v interface{}) ([]byte, error)

func (*ProtobufSerializer) Unmarshal

func (p *ProtobufSerializer) Unmarshal(data []byte, v interface{}) error

type RateLimiter added in v0.4.0

type RateLimiter interface {
	AllowClient(clientId string) bool

	AllowIP(ip string) bool

	AllowNetAddr(addr net.Addr) bool

	Stop()
}

type RateLimiterConfig added in v0.4.0

type RateLimiterConfig struct {
	// PerClientRate is requests/msgs per second allowed per client.
	PerClientRate float64
	// PerClientBurst is burst size for client limiter.
	PerClientBurst int

	// PerIPRate is requests/msgs per second allowed per IP (handshake / connection attempts / overall).
	PerIPRate float64
	// PerIPBurst is burst size for IP limiter.
	PerIPBurst int

	// CleanupInterval controls how often internal stale entries are purged.
	CleanupInterval time.Duration
	// EntryTTL is how long an unused entry stays before eligible for cleanup.
	EntryTTL time.Duration

	// MaxRateLimitViolations is the maximum number of times a client can be rate limited before being disconnected.
	MaxRateLimitViolations int
}

func DefaultRateLimiterConfig added in v0.4.0

func DefaultRateLimiterConfig() RateLimiterConfig

type RateLimiterManager added in v0.4.0

type RateLimiterManager struct {
	// contains filtered or unexported fields
}

func NewRateLimiterManager added in v0.4.0

func NewRateLimiterManager(config RateLimiterConfig) *RateLimiterManager

func (*RateLimiterManager) AllowClient added in v0.4.0

func (r *RateLimiterManager) AllowClient(clientID string) bool

AllowClient returns true if client with given id is allowed (token available). Should be called for each incoming message from the client.

func (*RateLimiterManager) AllowIP added in v0.4.0

func (r *RateLimiterManager) AllowIP(ip string) bool

AllowIP returns true if IP is allowed (token available). ip should be a canonical string (e.g., net.IP.String()).

func (*RateLimiterManager) AllowNetAddr added in v0.4.0

func (r *RateLimiterManager) AllowNetAddr(addr net.Addr) bool

AllowNetAddr is helper: extracts IP from net.Addr (e.g. ws conn.RemoteAddr())

func (*RateLimiterManager) Stop added in v0.4.0

func (r *RateLimiterManager) Stop()

type RawSerializer

type RawSerializer struct {
	BaseSerializer
}

RawSerializer to raw binary data

func NewRawSerializer added in v0.4.0

func NewRawSerializer(config SerializationConfig) *RawSerializer

func (*RawSerializer) ContentType

func (r *RawSerializer) ContentType() string

func (*RawSerializer) EncodingType

func (r *RawSerializer) EncodingType() EncodingType

func (*RawSerializer) Marshal

func (r *RawSerializer) Marshal(v interface{}) ([]byte, error)

func (*RawSerializer) Unmarshal

func (r *RawSerializer) Unmarshal(data []byte, v interface{}) error

type Room added in v0.5.0

type Room struct {
	OwnerId string
	Name    string
	Clients *SharedCollection[*Client]
}

func NewRoom added in v0.5.0

func NewRoom(ownerId, name string) *Room

type SerializationConfig added in v0.4.0

type SerializationConfig struct {
	MaxDepth        int
	MaxKeys         int
	MaxElements     int
	MaxStringLength int
	MaxBinarySize   int64
	DisallowedTypes []string
	EnableStrict    bool
}

func DefaultSerializerConfig added in v0.4.0

func DefaultSerializerConfig() SerializationConfig

type Serializer

type Serializer interface {
	// Marshal converts a Go value into a byte slice representation.
	//
	// The provided value is marshaled into a byte slice, which can be written to a stream or stored in a buffer.
	// Any error that occurs during marshaling is returned.
	Marshal(v interface{}) ([]byte, error)

	// Unmarshal converts a byte slice into a Go value.
	//
	// The provided byte slice is unmarshaled into the provided value.
	// Any error that occurs during unmarshaling is returned.
	Unmarshal(data []byte, v interface{}) error

	// ContentType returns the content type associated with the serialized data.
	//
	// The returned content type is a string that identifies the format of the serialized data.
	ContentType() string

	// EncodingType returns the type of encoding used by the serializer.
	//
	// The returned encoding type is an EncodingType value that identifies the encoding scheme used by the serializer.
	EncodingType() EncodingType

	Configure(config SerializationConfig)

	ValidateValue(v interface{}, depth int) error

	ValidateType(t reflect.Type, depth int) error
}

Serializer defines an interface for serializing and deserializing data.

func CreateSerializer added in v0.4.0

func CreateSerializer(encoding EncodingType, config SerializationConfig) Serializer

type Server

type Server struct {
	// contains filtered or unexported fields
}

func NewServer

func NewServer(options ...UniversalOption) (*Server, error)

New returns a new Server instance with default configuration.

func (*Server) Broadcast

func (s *Server) Broadcast(message []byte) error

Broadcast sends a raw message to all connected clients. The message is sent as a websocket.TextMessage. If the server is not properly initialized, this function will return an error.

func (*Server) BroadcastData

func (s *Server) BroadcastData(data interface{}) error

BroadcastData sends the given data to all connected clients. The data is serialized using the server's default encoding. If the default encoding is not set, the data will be sent as JSON. The data is sent as a websocket.TextMessage. If the server is not properly initialized, this function will return an error. If serialization fails, this function will return an error.

func (*Server) BroadcastDataWithEncoding

func (s *Server) BroadcastDataWithEncoding(data interface{}, encoding EncodingType) error

BroadcastDataWithEncoding sends the given data to all connected clients using the specified encoding type. The data is serialized using the matching serializer. If the serializer is not found, an error is returned. If serialization fails, an error is returned. The data is sent as a websocket.BinaryMessage. If the server is not properly initialized, this function will return an error.

func (*Server) BroadcastJSON

func (s *Server) BroadcastJSON(data interface{}) error

BroadcastJSON sends the given data to all connected clients as JSON. The data is marshaled to JSON and sent as a websocket.TextMessage. If the marshaling fails, an error is returned. If the server is not properly initialized, this function will return an error.

func (*Server) BroadcastMessage

func (s *Server) BroadcastMessage(message *Message) error

BroadcastMessage sends a Message to all connected clients. The message will be sent to each client according to the client's EncodingType. If the server is not properly initialized, this function will return an error.

func (*Server) BroadcastProtobuf

func (s *Server) BroadcastProtobuf(data interface{}) error

BroadcastProtobuf sends the given data to all connected clients as Protobuf. The data is marshaled to Protobuf and sent as a websocket.BinaryMessage. If the marshaling fails, an error is returned. If the server is not properly initialized, this function will return an error.

func (*Server) BroadcastToRoom

func (s *Server) BroadcastToRoom(room string, message []byte) error

BroadcastToRoom sends the given message to all clients in the specified room. The message is sent as a websocket.TextMessage. If the server is not properly initialized, this function will return an error.

func (*Server) BroadcastToRoomData

func (s *Server) BroadcastToRoomData(room string, data interface{}) error

BroadcastToRoomData sends the given data to all clients in the specified room. The data is serialized using the server's default encoding. If the default encoding is not set, the data will be sent as JSON. The data is sent as a websocket.TextMessage. If the server is not properly initialized, this function will return an error. If serialization fails, this function will return an error.

func (*Server) BroadcastToRoomJSON

func (s *Server) BroadcastToRoomJSON(room string, data interface{}) error

BroadcastToRoomJSON sends the given data to all clients in the specified room as JSON. The data is marshaled to JSON and sent as a websocket.TextMessage. If the marshaling fails, an error is returned. If the server is not properly initialized, this function will return an error.

func (*Server) BroadcastToRoomProtobuf

func (s *Server) BroadcastToRoomProtobuf(room string, data interface{}) error

BroadcastToRoomProtobuf sends the given data to all clients in the specified room as Protobuf. The data is marshaled to Protobuf and sent as a websocket.BinaryMessage. If the marshaling fails, an error is returned. If the server is not properly initialized, this function will return an error.

func (*Server) CreateRoom

func (s *Server) CreateRoom(name string) (*Room, error)

CreateRoom creates a new room with the given name. If the room already exists, the method will return nil. If the server is not properly initialized, an error is returned.

Thismethod is safe to call concurrently.

func (*Server) DeleteRoom

func (s *Server) DeleteRoom(name string) error

DeleteRoom deletes a room with the given name. If the room does not exist, it will return an error. If the server is not properly initialized, an error is returned.

This method is safe to call concurrently.

func (*Server) DisconnectClient

func (s *Server) DisconnectClient(id string) error

DisconnectClient removes the client with the specified ID from its hub and closes its connection. It will return nil if the client is not connected to a hub or if the connection is nil. Otherwise, it will return the error from closing the connection. If the client is not found, an error is returned.

This method is safe to call concurrently.

func (*Server) GetClient

func (s *Server) GetClient(id string) *Client

GetClient returns a client by its ID. If no client with the given ID exists, nil is returned. This method is safe to call concurrently.

func (*Server) GetClientCount

func (s *Server) GetClientCount() int

GetClientCount returns the number of clients currently connected to the server. If the server is not properly initialized, 0 is returned. This method is safe to call concurrently.

func (*Server) GetClients

func (s *Server) GetClients() []*Client

GetClients returns all clients currently connected to the server. If the server is not properly initialized, an empty slice is returned.

func (*Server) GetClientsInRoom

func (s *Server) GetClientsInRoom(room string) []*Client

GetClientsInRoom returns all clients in the specified room. If the server is not properly initialized or the room does not exist, an empty slice is returned. This method is safe to call concurrently.

func (*Server) GetRooms

func (s *Server) GetRooms() []string

GetRooms returns all rooms currently on the server. If the server is not properly initialized, an empty slice is returned.

This method is safe to call concurrently.

func (*Server) Handler added in v0.3.0

func (s *Server) Handler() *Handler

func (*Server) JoinRoom

func (s *Server) JoinRoom(clientID, room string) error

JoinRoom joins the given client to the given room. It will return an error if the client does not exist. If the client exists, it will call the JoinRoom method on the client.

This method is safe to call concurrently.

func (*Server) LeaveRoom

func (s *Server) LeaveRoom(clientID, room string) error

LeaveRoom removes the given client from the given room. It will return an error if the client does not exist.

This method is safe to call concurrently.

func (*Server) Start

func (s *Server) Start() (err error)

Start starts the GoSocket server. It will start listening on the configured port and path, and will begin accepting connections. If the server is already running, this function will return an error. If the port is invalid, this function will return an error. If the path is empty, this function will use the default path of "/ws". If there are no serializers configured, this function will use the JSON serializer by default. The server will be stopped using the Stop function, or by calling the Close method on the underlying net.Listener. If the server is stopped, this function will return an error. If the server encounters an error, this function will return an error.

func (*Server) StartWithContext

func (s *Server) StartWithContext(ctx context.Context) (err error)

StartWithContext starts the GoSocket server and returns an error. It will start listening on the configured port and path, and will begin accepting connections. If the server is already running, this function will return an error. If the port is invalid, this function will return an error. If the path is empty, this function will use the default path of "/ws". If there are no serializers configured, this function will use the JSON serializer by default. The server will be stopped using the Stop function, or by calling the Close method on the underlying net.Listener. If the server is stopped, this function will return an error. If the server encounters an error, this function will return an error. This function will also return an error if the provided context is canceled.

func (*Server) Stop

func (s *Server) Stop() error

Stop stops the GoSocket server and closes all active connections. This function will block until all active connections have been closed. If the server is not running, this function will return an error. If the server encounters an error while stopping, this function will return an error. This function will also return an error if the server's underlying net.Listener cannot be closed.

func (*Server) StopGracefully

func (s *Server) StopGracefully(timeout time.Duration) error

StopGracefully stops the GoSocket server and closes all active connections gracefully. This function will block until the context times out or all active connections have been closed. If the server is not running, this function will return an error. If the server encounters an error while stopping, this function will return an error. This function will also return an error if the server's underlying net.Listener cannot be closed.

func (*Server) With added in v0.3.0

func (s *Server) With(options ...UniversalOption) (*Server, error)

With applies the given options to the server. The options are applied in the order they are given, and if an option returns an error, the server will not be modified and the error will be returned. If no options are given, this function will return the server as is, with no error.

type ServerConfig

type ServerConfig struct {
	Port       int
	Path       string
	EnableCORS bool
	EnableSSL  bool
	CertFile   string
	KeyFile    string
}

func DefaultServerConfig

func DefaultServerConfig() *ServerConfig

type SharedCollection added in v0.5.0

type SharedCollection[T any] struct {
	sync.Mutex
	// contains filtered or unexported fields
}

A generic, thread-safe map of objectis with auto-incrementing IDs

func NewSharedCollection added in v0.5.0

func NewSharedCollection[T any](capacity ...int) *SharedCollection[T]

func (*SharedCollection[T]) Add added in v0.5.0

func (s *SharedCollection[T]) Add(obj T, id ...uint64) uint64

Add an object to the map with the given ID (if provided) or the next available ID Returns the ID of the object added

func (*SharedCollection[T]) AddWithStringId added in v0.5.0

func (s *SharedCollection[T]) AddWithStringId(obj T, stringId string) uint64

func (*SharedCollection[T]) ForEach added in v0.5.0

func (s *SharedCollection[T]) ForEach(callback func(id uint64, obj T))

Call the callback function for each object in the map

func (*SharedCollection[T]) ForEachWithStringId added in v0.5.0

func (s *SharedCollection[T]) ForEachWithStringId(callback func(id uint64, stringId string, obj T))

func (*SharedCollection[T]) Get added in v0.5.0

func (s *SharedCollection[T]) Get(id uint64) (T, bool)

Get and object with the given ID, if it exists, otherwise nil Also returns a boolean indication wheter the object was found

func (*SharedCollection[T]) GetAll added in v0.5.0

func (s *SharedCollection[T]) GetAll() []T

func (*SharedCollection[T]) GetByStringId added in v0.5.0

func (s *SharedCollection[T]) GetByStringId(stringId string) (T, bool)

Get and object with the given string ID, if it exists, otherwise nil Also returns a boolean indication wheter the object was found

func (*SharedCollection[T]) GetStringId added in v0.5.0

func (s *SharedCollection[T]) GetStringId(id uint64) (string, bool)

func (*SharedCollection[T]) HasStringId added in v0.5.0

func (s *SharedCollection[T]) HasStringId(stringId string) bool

func (*SharedCollection[T]) Len added in v0.5.0

func (s *SharedCollection[T]) Len() int

Get the approximate number of objects in the map The reason this is approximate is because the map is read without holding the lock

func (*SharedCollection[T]) Remove added in v0.5.0

func (s *SharedCollection[T]) Remove(id uint64) bool

Removes an object from the map by ID, if it exists Returns true if the object was removed

func (*SharedCollection[T]) RemoveByStringId added in v0.5.0

func (s *SharedCollection[T]) RemoveByStringId(stringId string) bool

Removes an object from the map by string ID, if it exists Returns true if the object was removed

type UniversalOption added in v0.3.0

type UniversalOption func(HasHandler) error

func OnBeforeConnect added in v0.4.0

func OnBeforeConnect(handler OnBeforeConnectFunc) UniversalOption

func OnConnect added in v0.3.0

func OnConnect(handler OnConnectFunc) UniversalOption

OnConnect sets a handler for the OnConnect event. The OnConnect event is called when a new client connects to the handler. The handler is called with the client that connected and a context object as arguments. The context object contains information about the client, such as the client's ID and the request that the client used to connect to the handler. The handler can return an error, which will be returned to the client. If the handler does not return an error, the client will be connected to the handler. The OnConnect handler can also be used to set the client's name and rooms. The OnConnect handler is called before the OnMessage handler is called.

func OnDisconnect added in v0.3.0

func OnDisconnect(handler OnDisconnectFunc) UniversalOption

OnDisconnect sets a handler for the OnDisconnect event. The OnDisconnect event is called when a client disconnects from the handler. The handler is called with the client that disconnected and a context object as arguments. The context object contains information about the client, such as the client's ID and the request that the client used to connect to the handler. The handler can return an error, which will be ignored. If the handler does not return an error, the client will be disconnected from the handler. The OnDisconnect handler is called after the client has been disconnected from the handler. The OnDisconnect handler can also be used to clean up resources associated with the client.

func OnError added in v0.3.0

func OnError(handler OnErrorFunc) UniversalOption

OnError sets a handler for the OnError event. The OnError event is called when the handler encounters an error while handling a client. The handler is called with the client that caused the error, the error that was encountered, and a context object as arguments. The context object contains information about the client, such as the client's ID and the request that the client used to connect to the handler. The handler can return an error, which will be ignored. If the handler does not return an error, the error will be logged. The OnError handler is called after the error has been logged. The OnError handler can also be used to clean up resources associated with the client.

func OnJSONMessage added in v0.3.0

func OnJSONMessage(handler OnJSONMessageFunc) UniversalOption

OnJSONMessage sets a handler for the OnJSONMessage event. The OnJSONMessage event is called when a client sends a JSON message to the handler. The handler is called with the client that sent the message, the unmarshaled JSON data, and a context object as arguments. The context object contains information about the client, such as the client's ID and the request that the client used to connect to the handler. The handler can return an error, which will be returned to the client. If the handler does not return an error, the message will be processed as usual. The OnJSONMessage handler is called after the OnRawMessage handler is called. The OnJSONMessage handler can also be used to modify the JSON data before it is processed by the handler.

func OnMessage added in v0.3.0

func OnMessage(handler OnMessageFunc) UniversalOption

OnMessage sets a handler for the OnMessage event. The OnMessage event is called when a client sends a message to the handler. The handler is called with the client that sent the message, the message that was sent, and a context object as arguments. The context object contains information about the client, such as the client's ID and the request that the client used to connect to the handler. The handler can return an error, which will be returned to the client. If the handler does not return an error, the message will be processed as usual. The OnMessage handler is called after the OnRawMessage handler is called. The OnMessage handler can also be used to modify the message before it is processed by the handler.

func OnPing added in v0.3.0

func OnPing(handler OnPingFunc) UniversalOption

OnPing sets a handler for the OnPing event. The OnPing event is called when the handler sends a ping message to a client. The handler is called with the client that received the ping message and a context object as arguments. The context object contains information about the client, such as the client's ID and the request that the client used to connect to the handler. The handler can return an error, which will be ignored. If the handler does not return an error, the ping message will be sent to the client as usual. The OnPing handler is called before the ping message is sent to the client. The OnPing handler can also be used to modify the ping message before it is sent to the client.

func OnPong added in v0.3.0

func OnPong(handler OnPongFunc) UniversalOption

OnPong sets a handler for the OnPong event. The OnPong event is called when a client responds to a ping message sent by the handler. The handler is called with the client that responded to the ping message and a context object as arguments. The context object contains information about the client, such as the client's ID and the request that the client used to connect to the handler. The handler can return an error, which will be ignored. If the handler does not return an error, the pong message will be processed as usual. The OnPong handler is called after the pong message is processed. The OnPong handler can also be used to clean up resources associated with the client.

func OnProtobufMessage added in v0.3.0

func OnProtobufMessage(handler OnProtobufMessageFunc) UniversalOption

OnProtobufMessage sets a handler for the OnProtobufMessage event. The OnProtobufMessage event is called when a client sends a Protobuf message to the handler. The handler is called with the client that sent the message, the unmarshaled Protobuf data, and a context object as arguments. The context object contains information about the client, such as the client's ID and the request that the client used to connect to the handler. The handler can return an error, which will be returned to the client. If the handler does not return an error, the message will be processed as usual. The OnProtobufMessage handler is called after the OnRawMessage handler is called. The OnProtobufMessage handler can also be used to modify the Protobuf data before it is processed by the handler.

func OnRawMessage added in v0.3.0

func OnRawMessage(handler OnRawMessageFunc) UniversalOption

OnRawMessage sets a handler for the OnRawMessage event. The OnRawMessage event is called when a client sends a message to the handler. The handler is called with the client that sent the message, the message that was sent, and a context object as arguments. The context object contains information about the client, such as the client's ID and the request that the client used to connect to the handler. The handler can return an error, which will be returned to the client. If the handler does not return an error, the message will be processed as usual. The OnRawMessage handler is called before the OnMessage handler is called. The OnRawMessage handler can also be used to modify the message before it is processed by the OnMessage handler.

func WithAllowedOrigins added in v0.3.0

func WithAllowedOrigins(origins []string) UniversalOption

WithAllowedOrigins sets the allowed origins for a handler. If the origins are specified, the handler will only allow incoming requests from the specified origins. If the origins are empty, the handler will allow incoming requests from any origin. The origins must be in the format "scheme://host[:port]".

func WithAuth added in v0.3.0

func WithAuth(authFunc AuthFunc) UniversalOption

WithAuth sets an authentication function for a handler. The authentication function will be called with the original request as an argument when a new client connects to the handler. If the authentication function returns an error, the client will be immediately disconnected. If the authentication function does not return an error, the client will be authenticated and connected to the handler. The authentication function can return a value to be associated with the client, which can be accessed later in the OnConnect, OnDisconnect, OnMessage, OnRawMessage, OnJSONMessage, and OnProtobufMessage handlers. The authentication function can also return an error, which will be returned to the client. If the authentication function returns an error, the client will not be connected to the handler. If the authentication function does not return an error, the client will be connected to the handler. The authentication function is called before the OnConnect handler is called.

func WithCORS added in v0.3.0

func WithCORS(enabled bool) UniversalOption

WithCORS sets whether the server should enable Cross-Origin Resource Sharing (CORS) for incoming requests. If enabled, the server will include the Access-Control-Allow-Origin header in all responses. Note that this is a simple implementation and does not handle preflighted requests or other advanced CORS features. See https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS for more information.

func WithDisallowedTypes added in v0.4.0

func WithDisallowedTypes(types []string) UniversalOption

func WithEncoding added in v0.3.0

func WithEncoding(encoding EncodingType) UniversalOption

WithEncoding sets the default encoding for a handler. The encoding is used to serialize outgoing messages and deserialize incoming messages. The default encoding is JSON, but you can change it to any of the supported encodings (JSON, Protobuf, Raw). If the encoding is not supported, an error will be returned.

func WithJSONSerializer added in v0.3.0

func WithJSONSerializer() UniversalOption

WithJSONSerializer sets the default JSON serializer for a handler. The serializer will be used to serialize outgoing messages and deserialize incoming messages for the JSON encoding type. The default JSON serializer will be used if no other serializer is specified.

func WithLogger added in v0.4.0

func WithLogger(logger Logger, levels map[LogType]LogLevel) UniversalOption

func WithMaxBinarySize added in v0.4.0

func WithMaxBinarySize(size int64) UniversalOption

func WithMaxConnections added in v0.3.0

func WithMaxConnections(max int) UniversalOption

WithMaxConnections sets the maximum number of connections allowed for a handler. If the limit is exceeded, new connections will be rejected with an error. The limit must be greater than 0.

func WithMaxDepth added in v0.4.0

func WithMaxDepth(depth int) UniversalOption

func WithMaxElements added in v0.4.0

func WithMaxElements(elements int) UniversalOption

func WithMaxKeys added in v0.4.0

func WithMaxKeys(keys int) UniversalOption

func WithMessageBufferSize added in v0.4.0

func WithMessageBufferSize(size int) UniversalOption

func WithMessageSize added in v0.3.0

func WithMessageSize(size int64) UniversalOption

WithMessageSize sets the maximum size of an incoming message in bytes. If the message size is exceeded, the connection will be closed with an error. The size must be greater than 0.

func WithMiddleware added in v0.3.0

func WithMiddleware(middleware Middleware) UniversalOption

WithMiddleware adds a middleware to the handler. The middleware will be applied to the handler in the order it is specified. If no middlewares are specified, the handler will not apply any middlewares. The middleware will receive the original request and response as arguments, and can return a new request and response. If the middleware returns an error, the handler will return the error to the client. If the middleware does not return an error, the handler will call the next middleware in the chain. If the middleware chain returns an error, the handler will return the error to the client. If the middleware chain does not return an error, the handler will call the original handler with the modified request and response. If the original handler returns an error, the handler will return the error to the client. If the original handler does not return an error, the handler will return the result of the original handler to the client.

func WithPath added in v0.3.0

func WithPath(path string) UniversalOption

WithPath sets the path for the server to listen on. If the path is empty, it defaults to "/". If the path does not start with a slash, it is prepended with one.

func WithPingPong added in v0.3.0

func WithPingPong(pingPeriod, pongWait time.Duration) UniversalOption

WithPingPong sets the ping and pong wait periods for a handler. The ping period is the interval at which the handler sends a ping message to a client. The pong wait is the maximum time allowed for a client to respond to a ping message. If the pong wait is exceeded, the connection will be closed with an error. The ping and pong wait periods must be greater than 0 and the pong wait must be greater than the ping period.

func WithPort added in v0.3.0

func WithPort(port int) UniversalOption

WithPort sets the port number for the server to listen on. If the port is outside the valid range of 1-65535, a warning is printed to the console and the default port of 8080 is used instead.

func WithProtobufSerializer added in v0.3.0

func WithProtobufSerializer() UniversalOption

WithProtobufSerializer sets the default Protobuf serializer for a handler. The serializer will be used to serialize outgoing messages and deserialize incoming messages for the Protobuf encoding type. The default Protobuf serializer will be used if no other serializer is specified.

func WithRateLimit added in v0.4.0

func WithRateLimit(config RateLimiterConfig) UniversalOption

func WithRawSerializer added in v0.3.0

func WithRawSerializer() UniversalOption

WithRawSerializer sets the default Raw serializer for a handler. The serializer will be used to serialize outgoing messages and deserialize incoming messages for the Raw encoding type. The default Raw serializer will be used if no other serializer is specified.

func WithRelevantHeaders added in v0.4.0

func WithRelevantHeaders(headers []string) UniversalOption

func WithSSL added in v0.3.0

func WithSSL(certFile, keyFile string) UniversalOption

WithSSL enables SSL/TLS for the server. The server will only serve requests over HTTPS if this method is called with a valid certificate and key file. If either the certificate or key file is empty, SSL/TLS will not be enabled. The certificate and key file should be in PEM format.

func WithSerializer added in v0.3.0

func WithSerializer(encoding EncodingType, serializer Serializer) UniversalOption

WithSerializer sets a custom serializer for the specified encoding type.

The serializer will be used to serialize outgoing messages and deserialize incoming messages for the specified encoding type. The encoding type must be one of the supported encoding types (JSON, Protobuf, Raw). If the encoding type is not supported, an error will be returned.

The serializer will be used for all incoming and outgoing messages with the specified encoding type. If you want to use a different serializer for a specific message, you can use the WithEncoding option on the message.

func WithStrictSerialization added in v0.4.0

func WithStrictSerialization(enabled bool) UniversalOption

func WithTimeout added in v0.3.0

func WithTimeout(read, write time.Duration) UniversalOption

WithTimeout sets the read and write timeouts for a handler. If the read timeout is exceeded, the connection will be closed with an error. If the write timeout is exceeded, the write will be cancelled and the connection will be closed with an error. The timeouts must be greater than 0.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL