ws

package module
v0.0.0-...-12f43d0 Latest Latest
Warning

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

Go to latest
Published: Jan 28, 2018 License: MIT Imports: 7 Imported by: 2

README

ws

High level websocket server library for Go, built on top of gorilla.websocket

Install

go get github.com/eyesore/ws

Usage

Check out the complete documentation on godoc

Implement the Interface

This package exposes a pair of interfaces that might be implemented on any type to allow it to handle WebSocket connections.

Connector should implement Tornado-style event handlers for the stages of the WebSocket lifecycle:

  • OnConnect
  • OnOpen
  • OnClose

All callbacks must be implemented to fulfill the interface, but no-ops are fine. Returning an error from any callback will terminate the WebSocket connection.

The *Conn returned by Connector.Conn() is an io.ReadWriteCloser, and as such is safe for writing by multiple goroutines.

A Server must implement an additional callback OnMessage, which is how this type will interact with incoming messages rather than reading them. A Server may not access messages with Conn().Read - the Conn is already being read to in order for the callback to receive messages. See the godoc for full documentation.

Handle Incoming Connections Automatically With Handler

Handler is an http.Handler ready to serve incoming connections and upgrade them to WebSockets.

Factory is a function that returns a Connector (and an error, optionally).

Create a handler and serve it with package http:

h := ws.NewHandler(NewConnector)
http.Handle("/", h)

err := http.ListenAndServe(":80", nil)

Your Connectors will then manage new incoming connections with the callbacks you define.

Connector Example
type MyConnector struct {
    conn *ws.Conn
}

func (c *MyConnector) Conn() *ws.Conn {
    return c.conn
}

func (c *MyConnector) SetConn(conn *ws.Conn) {
    c.conn = conn
}

func (c *MyConnector) OnConnect(r *http.Request) error {
    return nil
}

func (c *MyConnector) OnOpen() error {
    return nil
}

func (c *MyConnector) OnClose(wasClean bool, code int, reason error) error {
    return nil
}

func New() (ws.Connector, error) {
    return &MyConnector{}, nil
}

func main() {
    h := ws.NewHandler(New)
    http.Handle("/", h)
    http.ListenAndServe(":8080", nil)
}
Advanced Configuration
Configure the Handler

Handler exports a reference to the underlying websocket.Upgrader that allows tight control over the configuration of the WebSocket connection. You can replace the Upgrader with your own, or configure as desired. The Handler also contains several configs that apply default values to each instance of the Connector. See the godoc for details.

Cross-Origin Access

Handler.Upgrader has a CheckOrigin method that can be overridden to control which origins are allowed to connect to your WebSocket server. There is also a convenience method: Handler.AllowAnyOrigin() that sets up a permissive policy. Do not call this method without understanding the risks!

In addition to configuring default settings on Handler, each Connector may modify Conn settings (both ws.Conn and websocket.Conn) during the OnOpen callback.

func(c *MyConnector) OnOpen() error {
    if c.shouldLimitMessageSize() {
        c.Conn().MaxMessageSize = 1024
    }
    // you can also access the underlying websocket.Conn
    c.Conn().Conn.EnableWriteCompression(true)
}

The OnConnect callback can be used to set the ResponseHeader for the upgrade request. You should check for sec-websocket-protocol header in the request and negotiate a subprotocol if appropriate.

func (c *MyConnector) OnConnect(r *http.Request) error {
    // do a better check than this
    if protocols := r.Header.Get("sec-websocket-protocol"); protocols != "" {
        var p string
        switch {
        case strings.Contains(protocols, "json"):
            p = "json"
        case strings.Contains(protocols, "xml"):
            p = "xml"
        }
        c.Conn().ResponseHeader.Add("sec-websocket-protocol", p)
    }
    return nil
}

Documentation

Overview

Package ws provides a websocket connection that implements io.ReadWriteCloser and some handy callbacks for managing websocket connections, as well as an http.Handler for automatically upgrading HTTP requests to WebSockets

Index

Constants

View Source
const (
	// ModeBinary causes Conn.Write to write binary messages.
	ModeBinary = websocket.BinaryMessage

	// ModeText causes Conn.Write to write text messages.
	ModeText = websocket.TextMessage
)

Variables

View Source
var (
	// ErrWriteTimeout means that outbox was blocking for longer than Conn.WriteTimeout
	ErrWriteTimeOut = errors.New("write timed out")
)

Functions

func SetDebug

func SetDebug(on bool)

SetDebug turns debug output on or off

Types

type Conn

type Conn struct {
	Conn *websocket.Conn
	// ResponseHeader can be modified eg. in OnConnect to be included in the initial http response
	ResponseHeader http.Header

	// PingInterval is how often we send a ping frame to make sure someone is still listening
	PingInterval time.Duration

	// PongTimeout is how long after sending a ping frame we will wait for a pong frame before closing the connection
	PongTimeout time.Duration

	MaxMessageSize int64
	WriteTimeout   time.Duration
	// contains filtered or unexported fields
}

Conn exposes per-socket connection configs, and implements io.ReadWriteCloser TODO - implement net.Conn?

func (*Conn) Close

func (c *Conn) Close() error

Close causes the connection to close. How about that?

func (*Conn) Read

func (c *Conn) Read(p []byte) (int, error)

Read implements io.Reader. If type information is needed, you can use ReadMessage. Both methods consume the same stream and should probably not be used together. WARNING: Read should only be used by ws.Handler that does not expose OnMessage Read will block indefinitely by default if ws.Server is implemented

func (*Conn) ReadMessage

func (c *Conn) ReadMessage(p []byte) (bytesRead int, isBinary bool, err error)

ReadMessage is an alternative to Read and Server.OnMessage that provides websocket messagetype information. Blocks until message is available for reading.

func (*Conn) SetMessageMode

func (c *Conn) SetMessageMode(m int)

SetMessageMode configures the types of messages that Conn will send with Write. This has no bearning on messages gotten from Read. Valid values for m are ws.ModeBinary or ws.ModeText

func (*Conn) Write

func (c *Conn) Write(m []byte) (int, error)

Write sends a message over the underlying websocket connection. Safe for concurrent use. The message type will be equal to c.messageType which can be configured with c.SetMessageMode. If writing both types is required, Conn.Conn().WriteMessage is available Implements io.ReadWriteCloser

type Connector

type Connector interface {
	// Conn and SetConn expose the underlying connection
	Conn() *Conn
	SetConn(*Conn)

	// callbacks
	OnConnect(*http.Request) error
	OnOpen() error
	OnClose(wasClean bool, code int, reason error) error
}

Connector handles Websocket connections by calling back on Connect, Open, and Close

type Factory

type Factory func() (Connector, error)

Factory creates a Connector

type Handler

type Handler struct {
	// Set options on Upgrader to configure
	Upgrader *websocket.Upgrader

	// default options will be passed on to each Server yielded by this Handler
	// PingInterval is how often we send a ping frame to make sure someone is still listening
	PingInterval time.Duration

	// PongTimeout is how long after sending a ping frame we will wait for a pong frame before closing the connection
	PongTimeout time.Duration

	MaxMessageSize int64
	WriteTimeout   time.Duration

	// ReadBufferSize determines the buffer size of the inbox channel
	// The purpose of the read buffer is to detect instances that are not consuming the
	// read buffer if used. Increase this if the buffer is filling faster than you can
	// consume it.
	ReadBufferSize int
	// contains filtered or unexported fields
}

Handler is an http.Handler that creates and spits out new WS connections

func NewHandler

func NewHandler(f Factory) *Handler

NewHandler returns a ready-to-use-or-configure Handler

func (*Handler) AllowAnyOrigin

func (h *Handler) AllowAnyOrigin()

AllowAnyOrigin causes the Conn not to reject any connection attempts based on origin

func (*Handler) ServeHTTP

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP satisfies http.Handler - errors just write 500 InternalServerError

type Server

type Server interface {
	Connector

	// OnMessage is called each time a message is received on the Conn if implemented.
	// If implemented, Read should not be called as it will not receive the messages
	// and will instead block indefinitely.
	// TODO allow configuration to use both?
	OnMessage(payload []byte, isBinary bool) error
}

Server serves Websocket connections by calling back on Connect, Open, Message, and Close

Jump to

Keyboard shortcuts

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