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 ¶
- func SetLogger(logger logging.Logger)
- type Channel
- type CheckClientHandler
- type Client
- type ClientOpt
- type ClientTimeoutConfig
- type ConnectedHandler
- type DisconnectedHandler
- type ErrorHandler
- type HttpConnectionError
- type MessageHandler
- type PingConfig
- type Server
- type ServerOpt
- type ServerTimeoutConfig
- type WebSocketConfig
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Channel ¶
type Channel interface {
// ID returns the unique identifier of the client, which identifies this unique channel.
ID() string
// RemoteAddr returns the remote IP network address of the connected peer.
RemoteAddr() net.Addr
// TLSConnectionState returns information about the active TLS connection, if any.
TLSConnectionState() *tls.ConnectionState
// IsConnected returns true if the connection to the peer is active, false if it was closed already.
IsConnected() bool
}
Channel represents a bi-directional IP-based communication channel, which provides at least a unique ID.
type Client ¶
type Client 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)
// Stop 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.
//
// It is recommended to invoke this function before starting a client.
// Creating the error channel while the client is running may lead to unexpected behavior.
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)
}
Client 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 secure websocket client instead, pass a tls.Config to the NewClient function:
certPool, err := x509.SystemCertPool()
if err != nil {
log.Fatal(err)
}
// You may add more trusted certificates to the pool before creating the TLS Config
client := NewClient(&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.
func NewClient ¶
NewClient creates a new websocket client.
If the optional tlsConfig is not nil, and the server supports secure communication, the websocket channel will use TLS.
Additional options may be added using the AddOption function.
Basic authentication can be set using the SetBasicAuth function.
By default, the client will not negotiate any sub-protocol. This value needs to be set via the respective SetRequestedSubProtocol method.
To set a client certificate, you may do:
certificate, _ := tls.LoadX509KeyPair(clientCertPath, clientKeyPath)
clientCertificates := []tls.Certificate{certificate}
client := ws.NewClient(ws.WithClientTLSConfig(&tls.Config{
RootCAs: certPool,
Certificates: clientCertificates,
}))
You can set any other TLS option within the same constructor config 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
type ClientOpt ¶
type ClientOpt func(c *client)
ClientOpt is a function that can be used to set options on a client during creation.
type ClientTimeoutConfig ¶
type ClientTimeoutConfig struct {
WriteWait time.Duration // The timeout for network write operations. After a timeout, the connection is closed.
HandshakeTimeout time.Duration // The timeout for the initial handshake to complete.
PongWait time.Duration // The timeout for waiting for a pong from the server. After a timeout, the connection is closed. Needs to be set, if client is configured to send ping messages.
PingPeriod time.Duration // The interval for sending ping messages to a server. If set to 0, no pings are sent.
RetryBackOffRepeatTimes int
RetryBackOffRandomRange int
RetryBackOffWaitMinimum time.Duration
}
ClientTimeoutConfig 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 ¶
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 ¶
HttpConnectionError is a websocket-specific error propagated to the upper layers when opening a websocket fails.
func (HttpConnectionError) Error ¶
func (e HttpConnectionError) Error() string
type PingConfig ¶
type PingConfig struct {
PingPeriod time.Duration // The interval for sending ping messages to the connected peer.
PongWait time.Duration // The timeout for waiting for a pong from the connected peer. After a timeout, the connection is closed.
}
PingConfig contains optional configuration parameters for websockets sending ping operations.
type Server ¶
type Server 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 MessageHandler)
// SetNewClientHandler 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.
//
// The callback is invoked after a connection was established and upgraded successfully.
// If custom checks need to be run beforehand, refer to SetCheckClientHandler.
SetNewClientHandler(handler ConnectedHandler)
// 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)
// Write 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
// AddSupportedSubprotocol 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)
// SetChargePointIdResolver sets the callback function to use for resolving the charge point ID of a charger connecting to
// the websocket server. By default, this will just be the path in the URL used by the client.
SetChargePointIdResolver(resolver func(r *http.Request) (string, error))
// 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.
// The handler is executed before any connection upgrade and allows optionally returning a custom
// configuration for the web socket that will be created.
//
// Changes to the http request at runtime may lead to undefined behavior.
SetCheckClientHandler(handler CheckClientHandler)
// 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
// GetChannel retrieves an active Channel connection by its unique identifier.
// If a connection with the given ID exists, it returns the corresponding webSocket instance.
// If no connection is found with the specified ID, it returns nil and a false flag.
GetChannel(websocketId string) (Channel, bool)
}
Server 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 server with TLS support, pass the following option:
server := NewServer(WithServerTLSConfig("cert.pem", "privateKey.pem", nil))
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.
func NewServer ¶
NewServer Creates a new websocket server.
Additional options may be added using the AddOption function.
By default, the websockets are not secure, and the server will not perform any client certificate verification.
To add TLS support to the server, a valid server certificate path and key must be passed. To also add support for client certificate verification, a valid TLSConfig needs to be configured. For example:
tlsConfig := &tls.Config{
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: clientCAs,
}
server := ws.NewServer(ws.WithServerTLSConfig("cert.pem", "privateKey.pem", tlsConfig))
When TLS is correctly configured, the server will automatically use it for all created websocket channels.
type ServerOpt ¶
type ServerOpt func(s *server)
ServerOpt is a function that can be used to set options on a server during creation.
type ServerTimeoutConfig ¶
type ServerTimeoutConfig struct {
WriteWait time.Duration // The timeout for network write operations. After a timeout, the connection is closed.
PingWait time.Duration // The timeout for waiting for a ping from the client. After a timeout, the connection is closed.
PingPeriod time.Duration // The interval for sending ping messages to a client. If set to 0, no pings are sent.
PongWait time.Duration // The timeout for waiting for a pong from the server. After a timeout, the connection is closed. Needs to be set, if server is configured to send ping messages.
}
ServerTimeoutConfig 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 ¶
func NewServerTimeoutConfig() ServerTimeoutConfig
NewServerTimeoutConfig creates a default timeout configuration for a websocket endpoint. In the default configuration, server-side ping messages are disabled.
You may change fields arbitrarily and pass the struct to a SetTimeoutConfig method.
type WebSocketConfig ¶
type WebSocketConfig struct {
// The timeout for network write operations.
// After a timeout, the connection is closed.
WriteWait time.Duration
// The timeout for waiting for a message from the connected peer.
// After a timeout, the connection is closed.
// If ReadWait is zero, the websocket will not time out on read operations.
//
// Depending on the configuration, the websocket will either wait for incoming pings
// or send pings to the connected peer.
//
// If PingConfig is set (i.e. the websocket is configured to send ping messages),
// the ReadWait value should be omitted.
// If provided, the websocket will accept ping messages, but the read timeout
// configuration from the PingConfig will be prioritized.
ReadWait time.Duration
// Optional configuration for ping operations. If omitted, the websocket will not send any pings.
PingConfig *PingConfig
// Optional logger for the websocket. If omitted, the global logger is used.
Logger logging.Logger
}
WebSocketConfig is a utility config struct for a single webSocket. By default, it inherits values from respective the ClientTimeoutConfig or ServerTimeoutConfig. However, during creation, some fields may be overridden and customized on a websocket-basis.
func NewDefaultWebSocketConfig ¶
func NewDefaultWebSocketConfig( writeWait time.Duration, readWait time.Duration, pingPeriod time.Duration, pongWait time.Duration) WebSocketConfig
NewDefaultWebSocketConfig creates a new websocket config struct with the passed values. If sendPing is set, the websocket will be configured to send out periodic pings.
No custom configuration functions are run. Overrides need to be applied externally.
Source Files
¶
- client.go
- server.go
- websocket.go