gows

package module
v1.0.4 Latest Latest
Warning

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

Go to latest
Published: Jul 9, 2025 License: CC-BY-4.0 Imports: 17 Imported by: 0

README

Go-WS: A High-Level WebSocket Library for Go

Go-WS is a wrapper built around Gorilla WebSocket, designed to simplify and accelerate WebSocket communication for both server and client implementations in Go.
It introduces high-level event emitters, request-response abstractions, and message parsing logic, making it ideal for building scalable real-time applications.

Features

  • Easy WebSocket server and client setup
  • Event-driven architecture (connection, disconnection, errors, messages)
  • Request-response pattern built-in
  • Custom message parsing and typed handler registration
  • Graceful connection handling with ID assignment
  • Thread-safe message sending
  • TLS certificate support (generate/load/save)
  • Reconnectable clients

Installation

go get github.com/GTedZ/gows

Getting Started

1. Setting Up a WebSocket Server
server := gows.NewServer("0.0.0.0", "/ws")
err := server.ListenAndServe(3000)
if err != nil {
    fmt.Println("ListenAndServe error", err.Error())
}

2. Configuring Origin Check (optional)
server.SetCheckOrigin(
    func(r *http.Request) bool {
        return true // Allow all origins
    },
)
Or just allow all (default):
server.SetCheckOrigin(nil)

3. Handling Events
server.OnConnect = func(conn *gows.Connection) {
    fmt.Println("New client connected")
}

server.OnClose = func(conn *gows.Connection, code int, reason string) {
    fmt.Println("Client disconnected:", reason)
}

4. Connection-Level Metadata (Custom Key-Value Store)

Each connection holds a thread-safe key-value store:

conn.SetString("username", "alice")
user, exists := conn.GetString("username")

5. Sending Text or JSON Messages
conn.SendText("Hello Client!")

conn.SendJSON(struct {
    Event string
    Data  string
}{
    Event: "greeting",
    Data:  "Hello!",
})

Websocket Client

1. Connecting to a Server
client, err := gows.NewClient("ws://localhost:3000/ws")
if err != nil {
    panic(err)
}

2. Receiving Messages
client.OnMessage = func(messageType int, msg []byte) {
    fmt.Println("Received:", string(msg))
}

3. 🔄 Request-Response Pattern
// Client
req := map[string]interface{}{"method": "ping"}
resp, timedOut, err := client.SendPrivateMessage(req)
// Server
conn.OnRequest = func(msg []byte, req *gows.ResponseHandler) {
    res := map[string]interface{}{"reply": "pong"}
    req.Reply(res)
}
  • Both client and server can initiate requests.
  • Uses a private field like "id" to match requests/responses.
  • Customize this field name using SetRequestIdPropertyName().

4. 🧠 Message Parsers (Core Feature)

Typed dispatching of messages using JSON structure matching:

Example Type
type Candlestick struct {
    Timestamp int64
    Open      float64
    High      float64
    Low       float64
    Close     float64
    Volume    float64
}
Registering a Parser on Client or Server
gows.RegisterMessageParserCallback(
    client.GetParserRegistry(),

    func(b []byte) (bool, *Candlestick) {   // Parser function, make sure to be overly explicit, a <nil> error from Unmarshal isn't enough
        var c Candlestick
        err := json.Unmarshal(b, &c)
        return err == nil && c.Timestamp > 0, &c
    },

    func(c *Candlestick) {                  // Callback
        fmt.Println("Parsed candlestick:", c)
    },
)
Parser Function Format
func(b []byte) (bool, *YourType)
  • bool: whether this message matches
  • *YourType: parsed struct to forward to the callback

Alternatively, pass nil for the parser to use default json.Unmarshal.


5. 🔐 TLS Support
Generate Self-Signed Certificate
cert, certPEM, keyPEM, _ := gows.Certificates.GenerateSelfSignedCert("localhost")
gows.Certificates.SaveCertToFiles(certPEM, keyPEM, "cert.pem", "key.pem")
Start TLS Server
server.ListenAndServeTLS(443, cert)

Or load certs from files:

server.ListenAndServeTLSWithFiles(443, "cert.pem", "key.pem")
Event Triggered When
OnConnect A new client connects
OnClose A client disconnects
OnMessage Any message received
OnRequest A private message (request) arrives
OnReconnect Client successfully reconnects
OnError Any socket-level error occurs

Example: Echo Server and Client

Server
server := gows.NewServer("0.0.0.0", "/ws")
server.OnConnect = func(conn *gows.Connection) {
    conn.OnMessage = func(_ int, msg []byte) {
        conn.SendText("Echo: " + string(msg))
    }
}
server.ListenAndServe(9000)
Client
client, _ := gows.NewClient("ws://localhost:9000/ws")
client.OnMessage = func(_ int, msg []byte) {
    fmt.Println("Reply:", string(msg))
}
client.SendText("Hello!")

Contributions

Feel free to submit issues and pull requests. Feedback and improvements are welcome.

Support

If you would like to support my projects, you can donate to the following addresses:

BTC: 19XC9b9gkbNVTB9eTPzjByijmx8gNd2qVR

ETH (ERC20): 0x7e5db6e135da1f4d5de26f7f7d4ed10dada20478

USDT (TRC20): TLHo8zxBpFSTdyuvvCTG4DzXFfDfv49EMu

SOL: B3ZKvA3yCm5gKLb7vucU7nu8RTnp6MEAPpfeySMSMoDc

Thank you for your support!


Documentation

Index

Constants

This section is empty.

Variables

View Source
var Certificates certificateHandler

Functions

This section is empty.

Types

type Client

type Client struct {
	OnMessage func(messageType int, msg []byte)

	// Called on any error that originates from the current established connection.
	//
	// Do not treat this as a disconnection as it can be triggerred multiple times for the same connection and is not a sign of disconnection
	//
	// Use 'OnDisconnect' instead in that case
	OnError func(err error)

	// Called once the connection unexpectedly drops, expect to be reconnected shortly after
	OnDisconnect func(code int, reason string)

	OnReconnectError func(err error)
	// Called once a new connection is established after disconnection
	OnReconnect func()
	// contains filtered or unexported fields
}

func NewClient

func NewClient(URL string, opt_params ...Client_params) (*Client, error)

func (*Client) Close

func (socket *Client) Close()

func (*Client) GetParserRegistry

func (socket *Client) GetParserRegistry() *parser.MessageParsers_Registry

func (*Client) SendJSON

func (socket *Client) SendJSON(v interface{}) error

func (*Client) SendPreparedMessage

func (socket *Client) SendPreparedMessage(preparedMessage *ws.PreparedMessage) error

func (*Client) SendPrivateMessage

func (socket *Client) SendPrivateMessage(message map[string]interface{}, timeout_sec ...int) (response []byte, hasTimedOut bool, err error)

func (*Client) SendText

func (socket *Client) SendText(text string) error

func (*Client) SetHTTPHeader

func (socket *Client) SetHTTPHeader(httpHeader http.Header)

func (*Client) SetURL

func (socket *Client) SetURL(URL string)

type Client_params

type Client_params struct {

	// Default is "id"
	PrivateRequestPropertyName string
	// contains filtered or unexported fields
}

type Connection

type Connection struct {
	Request *http.Request

	Data connectionData

	OnRequest func(msg []byte, request *ResponseHandler)
	OnMessage func(messageType int, msg []byte)
	OnError   func(err error)
	OnClose   func(code int, reason string)
	// contains filtered or unexported fields
}

func (*Connection) Close

func (connection *Connection) Close()

func (*Connection) GetId

func (connection *Connection) GetId() int

func (*Connection) GetParserRegistry

func (connection *Connection) GetParserRegistry() *parser.MessageParsers_Registry

func (*Connection) SendJSON

func (connection *Connection) SendJSON(v interface{}) error

func (*Connection) SendPreparedMessage

func (connection *Connection) SendPreparedMessage(message *ws.PreparedMessage) error

func (*Connection) SendText

func (connection *Connection) SendText(text string) error

type ResponseHandler

type ResponseHandler struct {
	Body []byte
	// contains filtered or unexported fields
}

func (*ResponseHandler) Reply

func (request *ResponseHandler) Reply(reply map[string]interface{}) error

func (*ResponseHandler) Unmarshal

func (request *ResponseHandler) Unmarshal(v interface{}) error

type Server

type Server struct {
	OnConnect func(*Connection)
	OnClose   func(connection *Connection, code int, reason string)

	Connections struct {
		Mu  sync.Mutex
		Map map[int]*Connection
	}
	// contains filtered or unexported fields
}

func NewServer

func NewServer(addr string, path string, opt_params ...Server_Params) *Server

func (*Server) Broadcast

func (server *Server) Broadcast(v interface{}) (failCount int, err error)

Broadcasts a message to all active connections to the server

'err' is returned only when preparing the message for broadcast goes wrong, meaning no connection was sent the message

Otherwise 'failCount' keeps track of how many connections failed to be sent the message

func (*Server) ListenAndServe

func (server *Server) ListenAndServe(port int) error

This method WILL block until the server is terminated or an error occurs

func (*Server) ListenAndServeTLS

func (server *Server) ListenAndServeTLS(port int, certificate tls.Certificate) error

This method WILL block until the server is terminated or an error occurs

func (*Server) ListenAndServeTLSWithFiles

func (server *Server) ListenAndServeTLSWithFiles(port int, certFile, keyFile string) error

This method WILL block until the server is terminated or an error occurs

func (*Server) SetCheckOrigin

func (server *Server) SetCheckOrigin(checkOrigin func(r *http.Request) bool)

CheckOrigin returns true if the request Origin header is acceptable. If CheckOrigin is nil, then a safe default is used: return false if the Origin request header is present and the origin host is not equal to request Host header.

A CheckOrigin function should carefully validate the request origin to prevent cross-site request forgery.

type Server_Params

type Server_Params struct {
	PrivateMessagePropertyName string
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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