github.com/philippseith/signalr@v0.6.3/clientoptions.go (about)

     1  package signalr
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  
     8  	"github.com/cenkalti/backoff/v4"
     9  )
    10  
    11  // WithConnection sets the Connection of the Client
    12  func WithConnection(connection Connection) func(party Party) error {
    13  	return func(party Party) error {
    14  		if client, ok := party.(*client); ok {
    15  			if client.connectionFactory != nil {
    16  				return errors.New("options WithConnection and WithConnector can not be used together")
    17  			}
    18  			client.conn = connection
    19  			return nil
    20  		}
    21  		return errors.New("option WithConnection is client only")
    22  	}
    23  }
    24  
    25  // WithConnector allows the Client to establish a connection
    26  // using the Connection build by the connectionFactory.
    27  // It is also used for auto reconnect if the connection is lost.
    28  func WithConnector(connectionFactory func() (Connection, error)) func(Party) error {
    29  	return func(party Party) error {
    30  		if client, ok := party.(*client); ok {
    31  			if client.conn != nil {
    32  				return errors.New("options WithConnection and WithConnector can not be used together")
    33  			}
    34  			client.connectionFactory = connectionFactory
    35  			return nil
    36  		}
    37  		return errors.New("option WithConnector is client only")
    38  	}
    39  }
    40  
    41  // HttpConnectionFactory is a connectionFactory for WithConnector which first tries to create a connection
    42  // with WebSockets (if it is allowed by the HttpConnection options) and if this fails, falls back to a SSE based connection.
    43  func HttpConnectionFactory(ctx context.Context, address string, options ...func(*httpConnection) error) (Connection, error) {
    44  	conn := &httpConnection{}
    45  	for i, option := range options {
    46  		if err := option(conn); err != nil {
    47  			return nil, err
    48  		}
    49  		if conn.transports != nil {
    50  			// Remove the WithTransports option
    51  			options = append(options[:i], options[i+1:]...)
    52  			break
    53  		}
    54  	}
    55  	// If no WithTransports was given, NewHTTPConnection fallbacks to both
    56  	if conn.transports == nil {
    57  		conn.transports = []TransportType{TransportWebSockets, TransportServerSentEvents}
    58  	}
    59  
    60  	for _, transport := range conn.transports {
    61  		// If Websockets are allowed, we try to connect with these
    62  		if transport == TransportWebSockets {
    63  			wsOptions := append(options, WithTransports(TransportWebSockets))
    64  			conn, err := NewHTTPConnection(ctx, address, wsOptions...)
    65  			// If this is ok, return the conn
    66  			if err == nil {
    67  				return conn, err
    68  			}
    69  			break
    70  		}
    71  	}
    72  	for _, transport := range conn.transports {
    73  		// If SSE is allowed, with fallback to try these
    74  		if transport == TransportServerSentEvents {
    75  			sseOptions := append(options, WithTransports(TransportServerSentEvents))
    76  			return NewHTTPConnection(ctx, address, sseOptions...)
    77  		}
    78  	}
    79  	// None of the transports worked
    80  	return nil, fmt.Errorf("can not connect with supported transports: %v", conn.transports)
    81  }
    82  
    83  // WithHttpConnection first tries to create a connection
    84  // with WebSockets (if it is allowed by the HttpConnection options) and if this fails, falls back to a SSE based connection.
    85  // This strategy is also used for auto reconnect if this option is used.
    86  // WithHttpConnection is a shortcut for WithConnector(HttpConnectionFactory(...))
    87  func WithHttpConnection(ctx context.Context, address string, options ...func(*httpConnection) error) func(Party) error {
    88  	return WithConnector(func() (Connection, error) {
    89  		return HttpConnectionFactory(ctx, address, options...)
    90  	})
    91  }
    92  
    93  // WithReceiver sets the object which will receive server side calls to client methods (e.g. callbacks)
    94  func WithReceiver(receiver interface{}) func(Party) error {
    95  	return func(party Party) error {
    96  		if client, ok := party.(*client); ok {
    97  			client.receiver = receiver
    98  			if receiver, ok := receiver.(ReceiverInterface); ok {
    99  				receiver.Init(client)
   100  			}
   101  			return nil
   102  		}
   103  		return errors.New("option WithReceiver is client only")
   104  	}
   105  }
   106  
   107  // WithBackoff sets the backoff.BackOff used for repeated connection attempts in the client.
   108  // See https://pkg.go.dev/github.com/cenkalti/backoff for configuration options.
   109  // If the option is not set, backoff.NewExponentialBackOff() without any further configuration will be used.
   110  func WithBackoff(backoffFactory func() backoff.BackOff) func(party Party) error {
   111  	return func(party Party) error {
   112  		if client, ok := party.(*client); ok {
   113  			client.backoffFactory = backoffFactory
   114  			return nil
   115  		}
   116  		return errors.New("option WithBackoff is client only")
   117  	}
   118  }
   119  
   120  // TransferFormat sets the transfer format used on the transport. Allowed values are "Text" and "Binary"
   121  func TransferFormat(format TransferFormatType) func(Party) error {
   122  	return func(p Party) error {
   123  		if c, ok := p.(*client); ok {
   124  			switch format {
   125  			case "Text":
   126  				c.format = "json"
   127  			case "Binary":
   128  				c.format = "messagepack"
   129  			default:
   130  				return fmt.Errorf("invalid transferformat %v", format)
   131  			}
   132  			return nil
   133  		}
   134  		return errors.New("option TransferFormat is client only")
   135  	}
   136  }