High level websocket server library for Go, built on top of gorilla.websocket
go get github.com/eyesore/ws
Check out the complete documentation on godoc
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:
OnConnectOnOpenOnClose
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.
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.
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)
}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.
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
}