signalr

package module
v2.4.0 Latest Latest
Warning

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

Go to latest
Published: Oct 6, 2022 License: MIT Imports: 17 Imported by: 6

README

PkgGoDev

Overview

This is my personal attempt at implementating the client side of the WebSocket portion of the SignalR protocol. I use it for various virtual currency trading platforms that use SignalR.

Examples

Simple example:

package main

import (
	"log"

	"github.com/rainhq/signalr/v2"
)

func main() {
	ctx := context.Background()

	// Prepare a SignalR client.
	c, err := signalr.Dial(
		ctx,
		"https://fake-server.definitely-not-real/signalr",
		`[{"name":"awesomehub"}]`,
	)
	if err != nil {
		log.Fatal(err)
	}

	var msg signalr.Message
	for {
		if err := c.ReadMessage(ctx, &msg); err != nil {
			log.Fatal(err)
		}

		log.Println(msg)
	}
}

Generic usage:

Cryptocurrency examples:

Proxy examples:

Documentation

Contribute

If anything is unclear or could be improved, please open an issue or submit a pull request. Thanks!

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.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsCloseError added in v2.3.0

func IsCloseError(err error, codes ...int) bool

Types

type CallbackStream added in v2.3.0

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

func (*CallbackStream) Close added in v2.3.0

func (s *CallbackStream) Close()

func (*CallbackStream) Read added in v2.3.0

func (s *CallbackStream) Read(args ...interface{}) error

type Client

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

func NewClient added in v2.3.0

func NewClient(hub string, conn *Conn) *Client

func (*Client) Callback added in v2.3.0

func (c *Client) Callback(ctx context.Context, method string) (*CallbackStream, error)

func (*Client) Close

func (c *Client) Close() error

Close closes underlying websocket connection

func (*Client) Invoke added in v2.3.0

func (c *Client) Invoke(ctx context.Context, method string, args ...interface{}) *Invocation

func (*Client) Run added in v2.3.0

func (c *Client) Run(ctx context.Context) error

type ClientMsg

type ClientMsg struct {
	// invocation identifier – allows to match up responses with requests
	InvocationID int `json:"I"`

	// the name of the hub
	Hub string `json:"H"`

	// the name of the method
	Method string `json:"M"`

	// arguments (an array, can be empty if the method does not have any
	// parameters)
	Args []json.RawMessage `json:"A"`

	// state – a dictionary containing additional custom data (optional)
	State *json.RawMessage `json:"S,omitempty"`
}

ClientMsg represents a message sent to the Hubs API from the client.

type CloseError added in v2.3.0

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

func (*CloseError) Error added in v2.3.0

func (e *CloseError) Error() string

type Conn added in v2.3.0

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

Conn represents a SignalR connection

func Dial

func Dial(ctx context.Context, endpoint, cdata string, opts ...DialOpt) (*Conn, error)

Dial connects to Signalr endpoint

func (*Conn) Close added in v2.3.0

func (c *Conn) Close() error

Close closes underlying websocket connection

func (*Conn) ReadMessage added in v2.3.0

func (c *Conn) ReadMessage(ctx context.Context, msg *Message) error

ReadMessage reads single message from websocket

func (*Conn) State added in v2.3.0

func (c *Conn) State() *State

func (*Conn) WriteMessage added in v2.3.0

func (c *Conn) WriteMessage(ctx context.Context, msg ClientMsg) error

Send sends a message to the websocket connection.

type ConnectError

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

func (*ConnectError) Error

func (e *ConnectError) Error() string

func (*ConnectError) Unwrap

func (e *ConnectError) Unwrap() error

type DialError

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

func (*DialError) Error

func (e *DialError) Error() string

func (*DialError) Unwrap

func (e *DialError) Unwrap() error

type DialOpt added in v2.3.0

type DialOpt func(*config)

func Dialer

func Dialer(dialer WebsocketDialerFunc) DialOpt

func HTTPClient

func HTTPClient(client *http.Client) DialOpt

func Headers

func Headers(headers http.Header) DialOpt

func MaxConnectRetries

func MaxConnectRetries(retries int) DialOpt

The maximum number of times to re-attempt a connection.

func MaxMessageProcessDuration added in v2.3.0

func MaxMessageProcessDuration(duration time.Duration) DialOpt

MaxMessageProcessDuration the maximum amount of time to spend on processing message

func MaxNegotiateRetries

func MaxNegotiateRetries(retries int) DialOpt

The maximum number of times to re-attempt a negotiation.

func MaxReconnectDuration

func MaxReconnectDuration(duration time.Duration) DialOpt

The maximum amount of time to spend retrying a reconnect attempt.

func MaxReconnectRetries added in v2.3.0

func MaxReconnectRetries(retries int) DialOpt

func MaxStartRetries

func MaxStartRetries(retries int) DialOpt

The maximum number of times to re-attempt a start command.

func Params

func Params(params url.Values) DialOpt

func Protocol

func Protocol(protocol string) DialOpt

func RetryInterval added in v2.3.0

func RetryInterval(interval time.Duration) DialOpt

The time to wait before retrying, in the event that an error occurs when contacting the SignalR service.

type DuplicateCallbackError added in v2.3.0

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

func (*DuplicateCallbackError) Error added in v2.3.0

func (e *DuplicateCallbackError) Error() string

type InvalidInitMessageError

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

func (*InvalidInitMessageError) Error

func (e *InvalidInitMessageError) Error() string

type InvalidStartResponseError

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

func (*InvalidStartResponseError) Error

func (e *InvalidStartResponseError) Error() string

type Invocation added in v2.3.0

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

func (*Invocation) Exec added in v2.3.0

func (r *Invocation) Exec() error

func (*Invocation) Unmarshal added in v2.3.0

func (r *Invocation) Unmarshal(dest interface{}) error

type InvocationError added in v2.3.0

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

func (*InvocationError) Error added in v2.3.0

func (e *InvocationError) Error() string

type Message

type Message struct {
	// message id, present for all non-KeepAlive messages
	MessageID string `json:"C"`

	// groups token – an encrypted string representing group membership
	GroupsToken string `json:"G"`

	InvocationID int `json:"I,string"`

	// an array containing actual data
	Messages []ClientMsg `json:"M"`

	// indicates that the transport was initialized (a.k.a. init message)
	Status int `json:"S"`

	// error
	Error       string                  `json:"E"`
	ErrorDetail *map[string]interface{} `json:"D"`
	HubError    bool                    `json:"H"`

	// result
	Result json.RawMessage `json:"R"`
}

Message represents a message sent from the server to the persistent websocket connection.

type NegotiateError

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

func (*NegotiateError) Error

func (e *NegotiateError) Error() string

func (*NegotiateError) Unwrap

func (e *NegotiateError) Unwrap() error

type ProxyFunc

type ProxyFunc func(req *http.Request) (*url.URL, error)

type ReadError

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

func (*ReadError) Error

func (e *ReadError) Error() string

func (*ReadError) Unwrap

func (e *ReadError) Unwrap() error

type ServerMsg

type ServerMsg struct {
	// invocation Id (always present)
	I int

	// the value returned by the server method (present if the method is not
	// void)
	R *json.RawMessage `json:",omitempty"`

	// error message
	E *string `json:",omitempty"`

	// true if this is a hub error
	H *bool `json:",omitempty"`

	// an object containing additional error data (can only be present for
	// hub errors)
	D *json.RawMessage `json:",omitempty"`

	// stack trace (if detailed error reporting (i.e. the
	// HubConfiguration.EnableDetailedErrors property) is turned on on the
	// server)
	T *json.RawMessage `json:",omitempty"`

	// state – a dictionary containing additional custom data (optional)
	S *json.RawMessage `json:",omitempty"`
}

ServerMsg represents a message sent to the Hubs API from the server.

type StartError

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

func (*StartError) Error

func (e *StartError) Error() string

func (*StartError) Unwrap

func (e *StartError) Unwrap() error

type State

type State struct {
	ConnectionData  string
	ConnectionID    string
	ConnectionToken string
	GroupsToken     string
	MessageID       string
	Protocol        string
}

State represents a SignalR connection state

type WebsocketConn

type WebsocketConn interface {
	ReadMessage(ctx context.Context) (messageType int, p []byte, err error)
	WriteMessage(ctx context.Context, messageType int, p []byte) error
	Close() 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.

type WebsocketDialer

type WebsocketDialer interface {
	Dial(ctx context.Context, u string, headers http.Header) (conn WebsocketConn, status int, err error)
}

func NewDefaultDialer added in v2.3.0

func NewDefaultDialer(client *http.Client) WebsocketDialer

type WebsocketDialerFunc

type WebsocketDialerFunc func(client *http.Client) WebsocketDialer

type WriteError

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

func (*WriteError) Error

func (e *WriteError) Error() string

func (*WriteError) Unwrap

func (e *WriteError) Unwrap() error

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

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