Documentation
¶
Overview ¶
Package signalr provides the client side implementation of the WebSocket portion of the SignalR protocol.
First things first: this was almost entirely written using https://blog.3d-logic.com/2015/03/29/signalr-on-the-wire-an-informal-description-of-the-signalr-protocol/ as a reference guide. It is an excellent technical write-up. Many thanks to Pawel Kadluczka for writing that and sharing it with the public. If you want deep-dive technical details of how this all works, read that blog. I won't try to replicate it here.
At a high level, the WebSocket portion of SignalR goes through the following steps:
- negotiate: use HTTP/HTTPS to get connection info for how to connect to the websocket endpoint
- connect: attempt to connect to the websocket endpoint
- start: make the WebSocket connection usable by SignalR connections
See the provided examples for how to use this library.
Example (Basic) ¶
This example shows the most basic way to start a websocket connection.
package main
import (
"log"
"github.com/carterjones/signalr"
)
func main() {
// Prepare a SignalR client.
c := signalr.New(
"fake-server.definitely-not-real",
"1.5",
"/signalr",
`[{"name":"awesomehub"}]`,
nil,
)
// Define message and error handlers.
msgHandler := func(msg signalr.Message) { log.Println(msg) }
panicIfErr := func(err error) {
if err != nil {
log.Panic(err)
}
}
// Start the connection.
err := c.Run(msgHandler, panicIfErr)
panicIfErr(err)
// Wait indefinitely.
select {}
}
Output:
Example (Complex) ¶
This example shows how to manually perform each of the initialization steps.
package main
import (
"log"
"github.com/carterjones/signalr"
)
func main() {
// Prepare a SignalR client.
c := signalr.New(
"fake-server.definitely-not-real",
"1.5",
"/signalr",
`[{"name":"awesomehub"}]`,
map[string]string{"custom-key": "custom-value"},
)
// Perform any optional modifications to the client here. Read the docs for
// all the available options that are exposed via public fields.
// Define message and error handlers.
msgHandler := func(msg signalr.Message) { log.Println(msg) }
panicIfErr := func(err error) {
if err != nil {
log.Panic(err)
}
}
// Manually perform the initialization routine.
err := c.Negotiate()
panicIfErr(err)
conn, err := c.Connect()
panicIfErr(err)
err = c.Start(conn)
panicIfErr(err)
// Begin the message reading loop.
go c.ReadMessages(msgHandler, panicIfErr)
// Wait indefinitely.
select {}
}
Output:
Index ¶
- func TestCompleteHandler(w http.ResponseWriter, r *http.Request)
- func TestConnect(w http.ResponseWriter, r *http.Request)
- func TestNegotiate(w http.ResponseWriter, r *http.Request)
- func TestReconnect(w http.ResponseWriter, r *http.Request)
- func TestStart(w http.ResponseWriter, r *http.Request)
- type Client
- func (c *Client) Close()
- func (c *Client) Conn() WebsocketConn
- func (c *Client) Connect() (*websocket.Conn, error)
- func (c *Client) Negotiate() error
- func (c *Client) ReadMessages(msgHandler MsgHandler, errHandler ErrHandler)
- func (c *Client) Reconnect() (*websocket.Conn, error)
- func (c *Client) Run(msgHandler MsgHandler, errHandler ErrHandler) error
- func (c *Client) Send(m hubs.ClientMsg) error
- func (c *Client) SetConn(conn WebsocketConn)
- func (c *Client) Start(conn WebsocketConn) error
- type ErrHandler
- type Message
- type MsgHandler
- type SafeString
- type Scheme
- type WebsocketConn
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func TestCompleteHandler ¶ added in v0.1.4
func TestCompleteHandler(w http.ResponseWriter, r *http.Request)
TestCompleteHandler combines the negotiate, connect, reconnect, and start handlers found in this package into one complete response handler.
func TestConnect ¶ added in v0.1.4
func TestConnect(w http.ResponseWriter, r *http.Request)
TestConnect provides a sample "/connect" handling function.
If an error occurs while upgrading the websocket, it will panic.
func TestNegotiate ¶ added in v0.1.4
func TestNegotiate(w http.ResponseWriter, r *http.Request)
TestNegotiate provides a sample "/negotiate" handling function.
If an error occurs while writing the response data, it will panic.
func TestReconnect ¶ added in v0.1.4
func TestReconnect(w http.ResponseWriter, r *http.Request)
TestReconnect provides a sample "/reconnect" handling function. It simply calls TestConnect.
Types ¶
type Client ¶
type Client struct {
// The host providing the SignalR service.
Host string
// The relative path where the SignalR service is provided.
Endpoint string
// The websockets protocol version.
Protocol string
// Connection data passed to the service's websocket.
ConnectionData string
// User-defined custom parameters passed with each request to the server.
Params map[string]string
// The HTTPClient used to initialize the websocket connection.
HTTPClient *http.Client
// An optional setting to provide a non-default TLS configuration to use
// when connecting to the websocket.
TLSClientConfig *tls.Config
// Either HTTPS or HTTP.
Scheme Scheme
// The maximum number of times to re-attempt a negotiation.
MaxNegotiateRetries int
// The maximum number of times to re-attempt a connection.
MaxConnectRetries int
// The maximum number of times to re-attempt a reconnection.
MaxReconnectRetries int
// The maximum number of times to re-attempt a start command.
MaxStartRetries int
// The time to wait before retrying, in the event that an error occurs
// when contacting the SignalR service.
RetryWaitDuration time.Duration
// The maximum amount of time to spend retrying a reconnect attempt.
MaxReconnectAttemptDuration time.Duration
// This is the connection token set during the negotiate phase of the
// protocol and used to uniquely identify the connection to the server
// in all subsequent phases of the connection.
ConnectionToken string
// This is the ID of the connection. It is set during the negotiate
// phase and then ignored by all subsequent steps.
ConnectionID string
// The groups token that is used during reconnect attempts.
//
// This is an example groups token:
// nolint:lll
// yUcSohHrAZGEwK62B4Ao0WYac82p5yeRvHHInBgVmSK7jX++ym3kIgDy466yW/gRPp2l3Py8G45mRLJ9FslB3sKfsDPUNWL1b54cvjaSXCUo0znzyACxrN2Y0kNLR59h7hb6PgOSfy3Z2R5CUSVm5LZg6jg=
GroupsToken SafeString
// The message ID that is used during reconnect attempts.
//
// This is an example message ID: d-8B839DC3-C,0|aaZe,0|aaZf,2|C1,2A801
MessageID SafeString
// Header values that should be applied to all HTTP requests.
Headers map[string]string
// This value is not part of the SignalR protocol. If this value is set,
// it will be used in debug messages.
CustomID string
// contains filtered or unexported fields
}
Client represents a SignlR client. It manages connections so that the caller doesn't have to.
func (*Client) Close ¶
func (c *Client) Close()
Close sends a signal to the loop reading WebSocket messages to indicate that the loop should terminate.
func (*Client) Conn ¶
func (c *Client) Conn() WebsocketConn
Conn returns the underlying websocket connection.
func (*Client) Negotiate ¶
Negotiate implements the negotiate step of the SignalR connection sequence.
func (*Client) ReadMessages ¶
func (c *Client) ReadMessages(msgHandler MsgHandler, errHandler ErrHandler)
ReadMessages processes WebSocket messages from the underlying websocket connection.
func (*Client) Reconnect ¶
Reconnect implements the reconnect step of the SignalR connection sequence.
func (*Client) Run ¶
func (c *Client) Run(msgHandler MsgHandler, errHandler ErrHandler) error
Run connects to the host and performs the websocket initialization routines that are part of the SignalR specification.
Example ¶
package main
import (
"log"
"github.com/carterjones/signalr"
)
func main() {
// Prepare a SignalR client.
c := signalr.New(
"fake-server.definitely-not-real",
"1.5",
"/signalr",
`[{"name":"awesomehub"}]`,
nil,
)
// Define handlers.
msgHandler := func(msg signalr.Message) { log.Println(msg) }
panicIfErr := func(err error) {
if err != nil {
log.Panic(err)
}
}
// Start the connection.
err := c.Run(msgHandler, panicIfErr)
if err != nil {
log.Panic(err)
}
// Wait indefinitely.
select {}
}
Output:
func (*Client) SetConn ¶
func (c *Client) SetConn(conn WebsocketConn)
SetConn changes the underlying websocket connection to the specified connection. This is done using a mutex to wait until existing read operations have completed.
func (*Client) Start ¶
func (c *Client) Start(conn WebsocketConn) error
Start implements the start step of the SignalR connection sequence.
type Message ¶
type Message struct {
// message id, present for all non-KeepAlive messages
C string
// an array containing actual data
M []hubs.ClientMsg
// indicates that the transport was initialized (a.k.a. init message)
S int
// groups token – an encrypted string representing group membership
G string
// other miscellaneous variables that sometimes are sent by the server
I string
E string
R json.RawMessage
H json.RawMessage // could be bool or string depending on a message type
D json.RawMessage
T json.RawMessage
}
Message represents a message sent from the server to the persistent websocket connection.
type SafeString ¶ added in v0.2.3
type SafeString struct {
// contains filtered or unexported fields
}
SafeString is a thread-safe string.
func (*SafeString) Get ¶ added in v0.2.3
func (s *SafeString) Get() string
Get returns the string value.
func (*SafeString) Set ¶ added in v0.2.3
func (s *SafeString) Set(str string)
Set sets the string value.
type Scheme ¶
type Scheme string
Scheme represents a type of transport scheme. For the purposes of this project, we only provide constants for schemes relevant to HTTP and websockets.
type WebsocketConn ¶
type WebsocketConn interface {
// ReadMessage is modeled after the function defined at
// https://godoc.org/github.com/gorilla/websocket#Conn.ReadMessage
//
// At a high level, it reads messages and returns:
// - the type of message read
// - the bytes that were read
// - any errors encountered during reading the message
ReadMessage() (messageType int, p []byte, err error)
// WriteJSON is modeled after the function defined at
// https://godoc.org/github.com/gorilla/websocket#Conn.WriteJSON
//
// At a high level, it writes a structure to the underlying websocket and
// returns any error that was encountered during the write operation.
WriteJSON(v interface{}) error
}
WebsocketConn is a combination of MessageReader and JSONWriter. It is used to provide an interface to objects that can read from and write to a websocket connection.
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
basic
command
|
|
|
bittrex
command
|
|
|
complex
command
|
|
|
cryptopia
command
|
|
|
proxy-authenticated
command
|
|
|
proxy-simple
command
|
|
|
Package hubs provides functionality used by the SignalR Hubs API.
|
Package hubs provides functionality used by the SignalR Hubs API. |