swaggersocket

package module
v0.0.0-...-ec92e0b Latest Latest
Warning

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

Go to latest
Published: Feb 21, 2017 License: Apache-2.0 Imports: 20 Imported by: 0

README

SwaggerSocket Build Status codecov Slack Status

license GoDoc

ReST over websocket, so you can serve swagger apis over websocket

Websocket Server

How to create a websocket server

A websocket server can be created using the NewWebSocketServer function

func NewWebSocketServer(opts SocketServerOpts) *WebsocketServer

The above function creates a websocket server based on the options structure passed to the constructor function

type SocketServerOpts struct {
   Addr      string
   KeepAlive bool
   PingHdlr  func(string) error
   PongHdlr  func(string) error
   AppData   []byte
   Log       Logger
}

Addr the ip address and port the websocket server is listening to KeepAlive activates the heartbeat mechanism at the server side PingHdlr A custom function to websocket ping messages (default is to send back a pong message) PongHdlr a custom function to a websocket pong message (default is nothing) AppData optional application-level data passed with the heartbeat messages Log custom logger

The Websocket Server Event Stream

After creating a websocket server, the user will probably need to listen the events happening on the websocket server.

To listen to the event stream of the websocket server

func (ss *WebsocketServer) EventStream() (<-chan ConnectionEvent, error)

The EventStream method returs a channel that carries ConnectionEvent instances

type ConnectionEvent struct {
	EventType    EvtType
	ConnectionId string
}

There are three types of connection events:

  • ConnectionReceived
  • ConnectionClosed
  • ConnectionFailure

The ConnectionEvent also has the ConnectionId field which is the ID of the connection associated with the event.

Websocket Client

A websocket client can be created using the NewWebSocketServer function

func NewWebSocketClient(opts SocketClientOpts) *WebsocketClient

This creates a websocket client based on the SocketClientOpts

type SocketClientOpts struct {
   URL       *url.URL
   KeepAlive bool
   PingHdlr  func(string) error
   PongHdlr  func(string) error
   AppData   []byte
   Logger    Logger
}

The URL is the url of the websocket server A KeepAlive set to true will activate the heartbeat mechanism from the client side and on connection failure, will attempt to reconnect to the websocket server with an exponential backoff.

Server-Client Handshake

This is a three-way handshake in the beginning of the connection. The purpose of this handshake is:

  • agree on a unique id ConnectionId for the connection
  • allowing the websocket client to store some connection metadata at the websocket server side

In particular, this is the sequence of events:

  1. The websocket Client sends an initial message to the websocket server with the connection metadata (if any)
  2. The websocket server stores the metadata for the connection and responds with a unique connection id
  3. The client confirms the reception of the connection id

The Heartbeat

The Heartbeat is the mechanism by which connection failures can be detected. The Heartbeat simply utilizes the underlying websocket ping/pong messages to send periodic heartbeat messages to check the health of the connection. Heartbeat messages can be activated at the websocket client and/or server sides by setting the KeepAlive field.

Swagger API Server

Websocket connections are bidirectional. This means the API server can be attached to either the websocket client or the websocket server.

If the api server is attached to the websocket client, the websocket server will act as the api client (issue requests to the websocket client and receive ap response)

After a connection has been established between the websocket server and the websocket client, the api server can be attached to any by hooking up the swagger api handler.

Attaching the Swagger API handler to the websocket server
wsServer := NewWebSocketServer(opts)
ch, err := wsServer.EventStream()
// the following loop is safe to run in a separate go-routine
for {
			select {
			case event := <-ch:
				if event.EventType == ConnectionReceived {
					conn := wsServer.connectionFromConnID(event.ConnectionId)
					conn.Serve(context.Background(), SwaggerAPIHandler)
				}

			case <-done:
				return
			}
}
Attaching the swagger api handler to the websocket client
// create a websocket client
wsClient := swaggersocket.NewWebSocketClient(clientOpts).WithMetaData("dummy connection metadata")
// connect to the websocket server
if err := wsClient.Connect(); err != nil {
		panic(err)
}
///////////////////
// some code goes here
//////////////////
// serve the swagger api on the websocket client
wsClient.Connection().Serve(context.Background(), SwaggerAPIHandler)

Swagger API Client

SocketConnection implements the RoundTripper interface. This means that the swagger client requires no modifications except for changing the RoundTripper of the runtime

For example, assuming that we are hooking the swagger client to the websocket client:

// create a websocket client
wsClient := swaggersocket.NewWebSocketClient(clientOpts).WithMetaData("dummy connection metadata")
// connect to the websocket server
if err := wsClient.Connect(); err != nil {
		panic(err)
}
///////////////////
// some code goes here
//////////////////
// runtime is the go-openapi runtime
rt := runtime.New("localhost", "/", []string{"https"})
rt.Transport = wsClient.Connection()
// client is the swagger http client
cli := client.New(rt, nil)

Documentation

Index

Constants

View Source
const TimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"

Variables

This section is empty.

Functions

This section is empty.

Types

type ConnectionEvent

type ConnectionEvent struct {
	EventType    EvtType
	ConnectionId string
}

type ConnectionType

type ConnectionType int

ConnectionType is the socket connection type, it can either be a serverside connection or a clientside connection

const (
	// ServerSide means this connection is owned by a websocket-server
	ServerSide ConnectionType = iota
	// ClientSide means this connection is owned by a websocket-client
	ClientSide
)

type EvtType

type EvtType int
const (
	ConnectionReceived EvtType = iota
	ConnectionClosed
	ConnectionFailure
)

func (EvtType) String

func (e EvtType) String() string

type Logger

type Logger interface {
	Print(...interface{})
	Printf(string, ...interface{})
	Println(...interface{})
}

Logger is the generic logger interface for in-app logging

type ResponseReader

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

ResponseReader is a specialized reader that reads streams on websockets

func (*ResponseReader) Read

func (rr *ResponseReader) Read(p []byte) (int, error)

type SocketClientOpts

type SocketClientOpts struct {
	URL       *url.URL
	KeepAlive bool
	PingHdlr  func(string) error
	PongHdlr  func(string) error
	AppData   []byte
	Logger    Logger
}

SocketClientOpts is the options for a socket client

type SocketConnection

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

SocketConnection is a wrapper around the websocket connection to handle http

func NewSocketConnection

func NewSocketConnection(opts connectionOpts) *SocketConnection

NewSocketConnection creates a new socket connection

func (*SocketConnection) Close

func (c *SocketConnection) Close() error

Close provides a graceful termination of the connection

func (*SocketConnection) ID

func (c *SocketConnection) ID() string

ID returns the connection id

func (*SocketConnection) ReadResponse

func (c *SocketConnection) ReadResponse() (*http.Response, error)

ReadResponse reads a response from the underlying connection

func (*SocketConnection) RoundTrip

func (c *SocketConnection) RoundTrip(req *http.Request) (*http.Response, error)

RoundTrip implements the http RoundTripper interface. Must be safe for concurrent use by multiple goroutines

func (*SocketConnection) Serve

func (c *SocketConnection) Serve(ctx context.Context, hdlr http.Handler)

func (*SocketConnection) WriteRequest

func (c *SocketConnection) WriteRequest(req *http.Request) error

WriteRequest writes a request to the underlying connection

type SocketServerOpts

type SocketServerOpts struct {
	Addr      string
	KeepAlive bool
	PingHdlr  func(string) error
	PongHdlr  func(string) error
	AppData   []byte
	Log       Logger
}

SocketServerOpts is the options for creating a websocket server

type WebsocketClient

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

WebsocketClient is the websockets client

func NewWebSocketClient

func NewWebSocketClient(opts SocketClientOpts) *WebsocketClient

NewWebSocketClient creates a new websocketcient

func (*WebsocketClient) Connect

func (sc *WebsocketClient) Connect() error

TODO refactor connect to return the connection instead of just an error. Creating a connection as a side effect is a bad idea Connect connects the websocket client to a server

func (*WebsocketClient) Connection

func (sc *WebsocketClient) Connection() *SocketConnection

Connection returns the socketConnection object

func (*WebsocketClient) WithMetaData

func (sc *WebsocketClient) WithMetaData(meta interface{}) *WebsocketClient

WithMetaData associates the socket client with app-level metadata

type WebsocketServer

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

func NewWebSocketServer

func NewWebSocketServer(opts SocketServerOpts) *WebsocketServer

NewWebSocketServer creates a new websocket server

func (*WebsocketServer) ActiveConnections

func (ss *WebsocketServer) ActiveConnections() []*SocketConnection

ActiveConnections returns all the active connections that the server currently has

func (*WebsocketServer) ConnectionFromID

func (ss *WebsocketServer) ConnectionFromID(id string) *SocketConnection

ConnectionFromID returns the SocketConnection object from the connection-id

func (*WebsocketServer) ConnectionFromMetaData

func (ss *WebsocketServer) ConnectionFromMetaData(meta interface{}) (string, error)

ConnectionFromMetaData returns the connection associated with the metadata

func (*WebsocketServer) EventStream

func (ss *WebsocketServer) EventStream() (<-chan ConnectionEvent, error)

EventStream is the socket server's event stream

func (*WebsocketServer) MetaData

func (ss *WebsocketServer) MetaData(cid string) interface{}

MetaData reads the metadata for some connection

func (*WebsocketServer) RemoteAddr

func (ss *WebsocketServer) RemoteAddr(connID string) string

RemoteAddr returns the remote address

Jump to

Keyboard shortcuts

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