ws

package
v0.18.0 Latest Latest
Warning

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

Go to latest
Published: Mar 12, 2024 License: MIT Imports: 15 Imported by: 35

Documentation

Overview

The package is a wrapper around gorilla websockets, aimed at simplifying the creation and usage of a websocket client/server.

Check the Client and Server structure to get started.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func SetLogger added in v0.16.0

func SetLogger(logger logging.Logger)

Sets a custom Logger implementation, allowing the package to log events. By default, a VoidLogger is used, so no logs will be sent to any output.

The function panics, if a nil logger is passed.

Types

type Channel

type Channel interface {
	ID() string
	RemoteAddr() net.Addr
	TLSConnectionState() *tls.ConnectionState
}

Channel represents a bi-directional communication channel, which provides at least a unique ID.

type CheckClientHandler added in v0.17.0

type CheckClientHandler func(id string, r *http.Request) bool

type Client

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

Client is the default implementation of a Websocket client.

Use the NewClient or NewTLSClient functions to create a new client.

func NewClient

func NewClient() *Client

Creates a new simple websocket client (the channel is not secured).

Additional options may be added using the AddOption function.

Basic authentication can be set using the SetBasicAuth function.

By default, the client will not neogtiate any subprotocol. This value needs to be set via the respective SetRequestedSubProtocol method.

func NewTLSClient

func NewTLSClient(tlsConfig *tls.Config) *Client

NewTLSClient creates a new secure websocket client. If supported by the server, the websocket channel will use TLS.

Additional options may be added using the AddOption function. Basic authentication can be set using the SetBasicAuth function.

To set a client certificate, you may do:

certificate, _ := tls.LoadX509KeyPair(clientCertPath, clientKeyPath)
clientCertificates := []tls.Certificate{certificate}
client := ws.NewTLSClient(&tls.Config{
	RootCAs:      certPool,
	Certificates: clientCertificates,
})

You can set any other TLS option within the same constructor as well. For example, if you wish to test connecting to a server having a self-signed certificate (do not use in production!), pass:

InsecureSkipVerify: true

func (*Client) AddOption

func (client *Client) AddOption(option interface{})

func (*Client) Errors added in v0.13.0

func (client *Client) Errors() <-chan error

func (*Client) IsConnected added in v0.14.0

func (client *Client) IsConnected() bool

func (*Client) SetBasicAuth added in v0.12.0

func (client *Client) SetBasicAuth(username string, password string)

func (*Client) SetDisconnectedHandler added in v0.14.0

func (client *Client) SetDisconnectedHandler(handler func(err error))

func (*Client) SetHeaderValue added in v0.13.0

func (client *Client) SetHeaderValue(key string, value string)

func (*Client) SetMessageHandler

func (client *Client) SetMessageHandler(handler func(data []byte) error)

func (*Client) SetReconnectedHandler added in v0.14.0

func (client *Client) SetReconnectedHandler(handler func())

func (*Client) SetRequestedSubProtocol added in v0.17.0

func (client *Client) SetRequestedSubProtocol(subProto string)

func (*Client) SetTimeoutConfig added in v0.13.0

func (client *Client) SetTimeoutConfig(config ClientTimeoutConfig)

func (*Client) Start

func (client *Client) Start(urlStr string) error

func (*Client) StartWithRetries added in v0.18.0

func (client *Client) StartWithRetries(urlStr string)

func (*Client) Stop

func (client *Client) Stop()

func (*Client) Write

func (client *Client) Write(data []byte) error

type ClientTimeoutConfig added in v0.13.0

type ClientTimeoutConfig struct {
	WriteWait               time.Duration
	HandshakeTimeout        time.Duration
	PongWait                time.Duration
	PingPeriod              time.Duration
	RetryBackOffRepeatTimes int
	RetryBackOffRandomRange int
	RetryBackOffWaitMinimum time.Duration
}

Config contains optional configuration parameters for a websocket client. Setting the parameter allows to define custom timeout intervals for websocket network operations.

To set a custom configuration, refer to the client's SetTimeoutConfig method. If no configuration is passed, a default configuration is generated via the NewClientTimeoutConfig function.

func NewClientTimeoutConfig added in v0.13.0

func NewClientTimeoutConfig() ClientTimeoutConfig

NewClientTimeoutConfig creates a default timeout configuration for a websocket endpoint.

You may change fields arbitrarily and pass the struct to a SetTimeoutConfig method.

type HttpConnectionError added in v0.12.0

type HttpConnectionError struct {
	Message    string
	HttpStatus string
	HttpCode   int
	Details    string
}

ConnectionError is a websocket

func (HttpConnectionError) Error added in v0.12.0

func (e HttpConnectionError) Error() string

type Server

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

Default implementation of a Websocket server.

Use the NewServer or NewTLSServer functions to create a new server.

func NewServer

func NewServer() *Server

Creates a new simple websocket server (the websockets are not secured).

func NewTLSServer

func NewTLSServer(certificatePath string, certificateKey string, tlsConfig *tls.Config) *Server

NewTLSServer creates a new secure websocket server. All created websocket channels will use TLS.

You need to pass a filepath to the server TLS certificate and key.

It is recommended to pass a valid TLSConfig for the server to use. For example to require client certificate verification:

tlsConfig := &tls.Config{
	ClientAuth: tls.RequireAndVerifyClientCert,
	ClientCAs: clientCAs,
}

If no tlsConfig parameter is passed, the server will by default not perform any client certificate verification.

func (*Server) AddHttpHandler added in v0.17.0

func (server *Server) AddHttpHandler(listenPath string, handler func(w http.ResponseWriter, r *http.Request))

func (*Server) AddSupportedSubprotocol

func (server *Server) AddSupportedSubprotocol(subProto string)

func (*Server) Addr added in v0.15.0

func (server *Server) Addr() *net.TCPAddr

func (*Server) Errors added in v0.13.0

func (server *Server) Errors() <-chan error

func (*Server) SetBasicAuthHandler added in v0.12.0

func (server *Server) SetBasicAuthHandler(handler func(username string, password string) bool)

func (*Server) SetCheckClientHandler added in v0.17.0

func (server *Server) SetCheckClientHandler(handler func(id string, r *http.Request) bool)

func (*Server) SetCheckOriginHandler added in v0.13.0

func (server *Server) SetCheckOriginHandler(handler func(r *http.Request) bool)

func (*Server) SetDisconnectedClientHandler

func (server *Server) SetDisconnectedClientHandler(handler func(ws Channel))

func (*Server) SetMessageHandler

func (server *Server) SetMessageHandler(handler func(ws Channel, data []byte) error)

func (*Server) SetNewClientHandler

func (server *Server) SetNewClientHandler(handler func(ws Channel))

func (*Server) SetTimeoutConfig added in v0.13.0

func (server *Server) SetTimeoutConfig(config ServerTimeoutConfig)

func (*Server) Start

func (server *Server) Start(port int, listenPath string)

func (*Server) Stop

func (server *Server) Stop()

func (*Server) StopConnection added in v0.15.0

func (server *Server) StopConnection(id string, closeError websocket.CloseError) error

func (*Server) Write

func (server *Server) Write(webSocketId string, data []byte) error

type ServerTimeoutConfig added in v0.13.0

type ServerTimeoutConfig struct {
	WriteWait time.Duration
	PingWait  time.Duration
}

Config contains optional configuration parameters for a websocket server. Setting the parameter allows to define custom timeout intervals for websocket network operations.

To set a custom configuration, refer to the server's SetTimeoutConfig method. If no configuration is passed, a default configuration is generated via the NewServerTimeoutConfig function.

func NewServerTimeoutConfig added in v0.13.0

func NewServerTimeoutConfig() ServerTimeoutConfig

NewServerTimeoutConfig creates a default timeout configuration for a websocket endpoint.

You may change fields arbitrarily and pass the struct to a SetTimeoutConfig method.

type WebSocket

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

WebSocket is a wrapper for a single websocket channel. The connection itself is provided by the gorilla websocket package.

Don't use a websocket directly, but refer to WsServer and WsClient.

func (*WebSocket) ID added in v0.15.0

func (websocket *WebSocket) ID() string

Retrieves the unique Identifier of the websocket (typically, the URL suffix).

func (*WebSocket) RemoteAddr added in v0.16.0

func (websocket *WebSocket) RemoteAddr() net.Addr

Returns the address of the remote peer.

func (*WebSocket) TLSConnectionState added in v0.15.0

func (websocket *WebSocket) TLSConnectionState() *tls.ConnectionState

Returns the TLS connection state of the connection, if any.

type WsClient

type WsClient interface {
	// Starts the client and attempts to connect to the server on a specified URL.
	// If the connection fails, an error is returned.
	//
	// For example:
	//	err := client.Start("ws://localhost:8887/ws/1234")
	//
	// The function returns immediately, after the connection has been established.
	// Incoming messages are passed automatically to the callback function, so no explicit read operation is required.
	//
	// To stop a running client, call the Stop function.
	Start(url string) error
	// Starts the client and attempts to connect to the server on a specified URL.
	// If the connection fails, it keeps retrying with Backoff strategy from TimeoutConfig.
	//
	// For example:
	//	client.StartWithRetries("ws://localhost:8887/ws/1234")
	//
	// The function returns only when the connection has been established.
	// Incoming messages are passed automatically to the callback function, so no explicit read operation is required.
	//
	// To stop a running client, call the Stop function.
	StartWithRetries(url string)
	// Closes the output of the websocket Channel, effectively closing the connection to the server with a normal closure.
	Stop()
	// Errors returns a channel for error messages. If it doesn't exist it es created.
	// The channel is closed by the client when stopped.
	Errors() <-chan error
	// Sets a callback function for all incoming messages.
	SetMessageHandler(handler func(data []byte) error)
	// Set custom timeout configuration parameters. If not passed, a default ClientTimeoutConfig struct will be used.
	//
	// This function must be called before connecting to the server, otherwise it may lead to unexpected behavior.
	SetTimeoutConfig(config ClientTimeoutConfig)
	// Sets a callback function for receiving notifications about an unexpected disconnection from the server.
	// The callback is invoked even if the automatic reconnection mechanism is active.
	//
	// If the client was stopped using the Stop function, the callback will NOT be invoked.
	SetDisconnectedHandler(handler func(err error))
	// Sets a callback function for receiving notifications whenever the connection to the server is re-established.
	// Connections are re-established automatically thanks to the auto-reconnection mechanism.
	//
	// If set, the DisconnectedHandler will always be invoked before the Reconnected callback is invoked.
	SetReconnectedHandler(handler func())
	// IsConnected Returns information about the current connection status.
	// If the client is currently attempting to auto-reconnect to the server, the function returns false.
	IsConnected() bool
	// Sends a message to the server over the websocket.
	//
	// The data is queued and will be sent asynchronously in the background.
	Write(data []byte) error
	// Adds a websocket option to the client.
	AddOption(option interface{})
	// SetRequestedSubProtocol will negotiate the specified sub-protocol during the websocket handshake.
	// Internally this creates a dialer option and invokes the AddOption method on the client.
	//
	// Duplicates generated by invoking this method multiple times will be ignored.
	SetRequestedSubProtocol(subProto string)
	// SetBasicAuth adds basic authentication credentials, to use when connecting to the server.
	// The credentials are automatically encoded in base64.
	SetBasicAuth(username string, password string)
	// SetHeaderValue sets a value on the HTTP header sent when opening a websocket connection to the server.
	//
	// The function overwrites previous header fields with the same key.
	SetHeaderValue(key string, value string)
}

WsClient defines a websocket client, needed to connect to a websocket server. The offered API are of asynchronous nature, and each incoming message is handled using callbacks.

To create a new ws client, use:

client := NewClient()

If you need a TLS ws client instead, use:

certPool, err := x509.SystemCertPool()
if err != nil {
	log.Fatal(err)
}
// You may add more trusted certificates to the pool before creating the TLSClientConfig
client := NewTLSClient(&tls.Config{
	RootCAs: certPool,
})

To add additional dial options, use:

client.AddOption(func(*websocket.Dialer) {
	// Your option ...
)}

To add basic HTTP authentication, use:

client.SetBasicAuth("username","password")

If you need to set a specific timeout configuration, refer to the SetTimeoutConfig method.

Using Start and Stop you can respectively open/close a websocket to a websocket server.

To receive incoming messages, you will need to set your own handler using SetMessageHandler. To write data on the open socket, simply call the Write function.

type WsServer

type WsServer interface {
	// Starts and runs the websocket server on a specific port and URL.
	// After start, incoming connections and messages are handled automatically, so no explicit read operation is required.
	//
	// The functions blocks forever, hence it is suggested to invoke it in a goroutine, if the caller thread needs to perform other work, e.g.:
	//	go server.Start(8887, "/ws/{id}")
	//	doStuffOnMainThread()
	//	...
	//
	// To stop a running server, call the Stop function.
	Start(port int, listenPath string)
	// Shuts down a running websocket server.
	// All open channels will be forcefully closed, and the previously called Start function will return.
	Stop()
	// Closes a specific websocket connection.
	StopConnection(id string, closeError websocket.CloseError) error
	// Errors returns a channel for error messages. If it doesn't exist it es created.
	// The channel is closed by the server when stopped.
	Errors() <-chan error
	// Sets a callback function for all incoming messages.
	// The callbacks accept a Channel and the received data.
	// It is up to the callback receiver, to check the identifier of the channel, to determine the source of the message.
	SetMessageHandler(handler func(ws Channel, data []byte) error)
	// Sets a callback function for all new incoming client connections.
	// It is recommended to store a reference to the Channel in the received entity, so that the Channel may be recognized later on.
	SetNewClientHandler(handler func(ws Channel))
	// Sets a callback function for all client disconnection events.
	// Once a client is disconnected, it is not possible to read/write on the respective Channel any longer.
	SetDisconnectedClientHandler(handler func(ws Channel))
	// Set custom timeout configuration parameters. If not passed, a default ServerTimeoutConfig struct will be used.
	//
	// This function must be called before starting the server, otherwise it may lead to unexpected behavior.
	SetTimeoutConfig(config ServerTimeoutConfig)
	// Sends a message on a specific Channel, identifier by the webSocketId parameter.
	// If the passed ID is invalid, an error is returned.
	//
	// The data is queued and will be sent asynchronously in the background.
	Write(webSocketId string, data []byte) error
	// Adds support for a specified subprotocol.
	// This is recommended in order to communicate the capabilities to the client during the handshake.
	// If left empty, any subprotocol will be accepted.
	//
	// Duplicates will be removed automatically.
	AddSupportedSubprotocol(subProto string)
	// SetBasicAuthHandler enables HTTP Basic Authentication and requires clients to pass credentials.
	// The handler function is called whenever a new client attempts to connect, to check for credentials correctness.
	// The handler must return true if the credentials were correct, false otherwise.
	SetBasicAuthHandler(handler func(username string, password string) bool)
	// SetCheckOriginHandler sets a handler for incoming websocket connections, allowing to perform
	// custom cross-origin checks.
	//
	// By default, if the Origin header is present in the request, and the Origin host is not equal
	// to the Host request header, the websocket handshake fails.
	SetCheckOriginHandler(handler func(r *http.Request) bool)
	// SetCheckClientHandler sets a handler for validate incoming websocket connections, allowing to perform
	// custom client connection checks.
	SetCheckClientHandler(handler func(id string, r *http.Request) bool)
	// Addr gives the address on which the server is listening, useful if, for
	// example, the port is system-defined (set to 0).
	Addr() *net.TCPAddr
}

WsServer defines a websocket server, which passively listens for incoming connections on ws or wss protocol. The offered API are of asynchronous nature, and each incoming connection/message is handled using callbacks.

To create a new ws server, use:

server := NewServer()

If you need a TLS ws server instead, use:

server := NewTLSServer("cert.pem", "privateKey.pem")

To support client basic authentication, use:

server.SetBasicAuthHandler(func (user, pass) bool {
	ok := authenticate(user, pass) // ... check for user and pass correctness
	return ok
})

To specify supported sub-protocols, use:

server.AddSupportedSubprotocol("ocpp1.6")

If you need to set a specific timeout configuration, refer to the SetTimeoutConfig method.

Using Start and Stop you can respectively start and stop listening for incoming client websocket connections.

To be notified of new and terminated connections, refer to SetNewClientHandler and SetDisconnectedClientHandler functions.

To receive incoming messages, you will need to set your own handler using SetMessageHandler. To write data on the open socket, simply call the Write function.

Jump to

Keyboard shortcuts

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