signalr

package module
v2.0.0-...-1985aaf Latest Latest
Warning

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

Go to latest
Published: Dec 10, 2022 License: MIT Imports: 17 Imported by: 1

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

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

Types

type CallbackStream

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

func (*CallbackStream) Close

func (s *CallbackStream) Close()

func (*CallbackStream) Read

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

func (*CallbackStream) ReadRaw

func (s *CallbackStream) ReadRaw() ClientMsg

type Client

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

func NewClient

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

func (*Client) Callback

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

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

func (*Client) Run

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

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

func (*CloseError) Error

func (e *CloseError) Error() string

type Conn

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

func (c *Conn) Close() error

Close closes underlying websocket connection

func (*Conn) ReadMessage

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

ReadMessage reads single message from websocket

func (*Conn) State

func (c *Conn) State() *State

func (*Conn) WriteMessage

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

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

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

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

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

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

func (*DuplicateCallbackError) Error

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

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

func (*Invocation) Exec

func (r *Invocation) Exec() error

func (*Invocation) Unmarshal

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

type InvocationError

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

func (*InvocationError) Error

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

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