Version: v0.0.0-...-20f3002 Latest Latest

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

Go to latest
Published: Jun 16, 2017 License: BSD-3-Clause, BSD-2-Clause, BSD-3-Clause Imports: 15 Imported by: 0




View Source
const (
	// DefaultWebsocketWriteTimeout 0, no timeout
	DefaultWebsocketWriteTimeout = 0
	// DefaultWebsocketReadTimeout 0, no timeout
	DefaultWebsocketReadTimeout = 0
	// DefaultWebsocketPongTimeout 60 * time.Second
	DefaultWebsocketPongTimeout = 60 * time.Second
	// DefaultWebsocketPingPeriod (DefaultPongTimeout * 9) / 10
	DefaultWebsocketPingPeriod = (DefaultWebsocketPongTimeout * 9) / 10
	// DefaultWebsocketMaxMessageSize 1024
	DefaultWebsocketMaxMessageSize = 1024
	// DefaultWebsocketReadBufferSize 4096
	DefaultWebsocketReadBufferSize = 4096
	// DefaultWebsocketWriterBufferSize 4096
	DefaultWebsocketWriterBufferSize = 4096
	// DefaultClientSourcePath "/iris-ws.js"
	DefaultClientSourcePath = "/iris-ws.js"
View Source
const (
	// All is the string which the Emitter use to send a message to all
	All = ""
	// Broadcast is the string which the Emitter use to send a message to all except this connection
	Broadcast = ";gowebsocket;to;all;except;me;"
View Source
const (
	// WriteWait is 1 second at the internal implementation,
	// same as here but this can be changed at the future*
	WriteWait = 1 * time.Second


View Source
var ClientSource = []byte(`var websocketStringMessageType = 0;
var websocketIntMessageType = 1;
var websocketBoolMessageType = 2;
// bytes is missing here for reasons I will explain somewhen
var websocketJSONMessageType = 4;
var websocketMessagePrefix = "iris-websocket-message:";
var websocketMessageSeparator = ";";
var websocketMessagePrefixLen = websocketMessagePrefix.length;
var websocketMessageSeparatorLen = websocketMessageSeparator.length;
var websocketMessagePrefixAndSepIdx = websocketMessagePrefixLen + websocketMessageSeparatorLen - 1;
var websocketMessagePrefixIdx = websocketMessagePrefixLen - 1;
var websocketMessageSeparatorIdx = websocketMessageSeparatorLen - 1;
var Ws = (function () {
    function Ws(endpoint, protocols) {
        var _this = this;
        // events listeners
        this.connectListeners = [];
        this.disconnectListeners = [];
        this.nativeMessageListeners = [];
        this.messageListeners = {};
        if (!window["WebSocket"]) {
        if (endpoint.indexOf("ws") == -1) {
            endpoint = "ws://" + endpoint;
        if (protocols != null && protocols.length > 0) {
            this.conn = new WebSocket(endpoint, protocols);
        else {
            this.conn = new WebSocket(endpoint);
        this.conn.onopen = (function (evt) {
            _this.isReady = true;
            return null;
        this.conn.onclose = (function (evt) {
            return null;
        this.conn.onmessage = (function (evt) {
    Ws.prototype.isNumber = function (obj) {
        return !isNaN(obj - 0) && obj !== null && obj !== "" && obj !== false;
    Ws.prototype.isString = function (obj) {
        return Object.prototype.toString.call(obj) == "[object String]";
    Ws.prototype.isBoolean = function (obj) {
        return typeof obj === 'boolean' ||
            (typeof obj === 'object' && typeof obj.valueOf() === 'boolean');
    Ws.prototype.isJSON = function (obj) {
        return typeof obj === 'object';
    // messages
    Ws.prototype._msg = function (event, websocketMessageType, dataMessage) {
        return websocketMessagePrefix + event + websocketMessageSeparator + String(websocketMessageType) + websocketMessageSeparator + dataMessage;
    Ws.prototype.encodeMessage = function (event, data) {
        var m = "";
        var t = 0;
        if (this.isNumber(data)) {
            t = websocketIntMessageType;
            m = data.toString();
        else if (this.isBoolean(data)) {
            t = websocketBoolMessageType;
            m = data.toString();
        else if (this.isString(data)) {
            t = websocketStringMessageType;
            m = data.toString();
        else if (this.isJSON(data)) {
            //propably json-object
            t = websocketJSONMessageType;
            m = JSON.stringify(data);
        else {
            console.log("Invalid, javascript-side should contains an empty second parameter.");
        return this._msg(event, t, m);
    Ws.prototype.decodeMessage = function (event, websocketMessage) {
        var skipLen = websocketMessagePrefixLen + websocketMessageSeparatorLen + event.length + 2;
        if (websocketMessage.length < skipLen + 1) {
            return null;
        var websocketMessageType = parseInt(websocketMessage.charAt(skipLen - 2));
        var theMessage = websocketMessage.substring(skipLen, websocketMessage.length);
        if (websocketMessageType == websocketIntMessageType) {
            return parseInt(theMessage);
        else if (websocketMessageType == websocketBoolMessageType) {
            return Boolean(theMessage);
        else if (websocketMessageType == websocketStringMessageType) {
            return theMessage;
        else if (websocketMessageType == websocketJSONMessageType) {
            return JSON.parse(theMessage);
        else {
            return null; // invalid
    Ws.prototype.getWebsocketCustomEvent = function (websocketMessage) {
        if (websocketMessage.length < websocketMessagePrefixAndSepIdx) {
            return "";
        var s = websocketMessage.substring(websocketMessagePrefixAndSepIdx, websocketMessage.length);
        var evt = s.substring(0, s.indexOf(websocketMessageSeparator));
        return evt;
    Ws.prototype.getCustomMessage = function (event, websocketMessage) {
        var eventIdx = websocketMessage.indexOf(event + websocketMessageSeparator);
        var s = websocketMessage.substring(eventIdx + event.length + websocketMessageSeparator.length + 2, websocketMessage.length);
        return s;
    // Ws Events
    // messageReceivedFromConn this is the func which decides
    // if it's a native websocket message or a custom qws message
    // if native message then calls the fireNativeMessage
    // else calls the fireMessage
    // remember q gives you the freedom of native websocket messages if you don't want to use this client side at all.
    Ws.prototype.messageReceivedFromConn = function (evt) {
        //check if qws message
        var message = evt.data;
        if (message.indexOf(websocketMessagePrefix) != -1) {
            var event_1 = this.getWebsocketCustomEvent(message);
            if (event_1 != "") {
                // it's a custom message
                this.fireMessage(event_1, this.getCustomMessage(event_1, message));
        // it's a native websocket message
    Ws.prototype.OnConnect = function (fn) {
        if (this.isReady) {
    Ws.prototype.fireConnect = function () {
        for (var i = 0; i < this.connectListeners.length; i++) {
    Ws.prototype.OnDisconnect = function (fn) {
    Ws.prototype.fireDisconnect = function () {
        for (var i = 0; i < this.disconnectListeners.length; i++) {
    Ws.prototype.OnMessage = function (cb) {
    Ws.prototype.fireNativeMessage = function (websocketMessage) {
        for (var i = 0; i < this.nativeMessageListeners.length; i++) {
    Ws.prototype.On = function (event, cb) {
        if (this.messageListeners[event] == null || this.messageListeners[event] == undefined) {
            this.messageListeners[event] = [];
    Ws.prototype.fireMessage = function (event, message) {
        for (var key in this.messageListeners) {
            if (this.messageListeners.hasOwnProperty(key)) {
                if (key == event) {
                    for (var i = 0; i < this.messageListeners[key].length; i++) {
    // Ws Actions
    Ws.prototype.Disconnect = function () {
    // EmitMessage sends a native websocket message
    Ws.prototype.EmitMessage = function (websocketMessage) {
    // Emit sends an q-custom websocket message
    Ws.prototype.Emit = function (event, data) {
        var messageStr = this.encodeMessage(event, data);
    return Ws;

ClientSource the client-side javascript raw source code

View Source
var (
	// DefaultIDGenerator returns the result of 64
	// random combined characters as the id of a new connection.
	// Used when config.IDGenerator is nil
	DefaultIDGenerator = func(context.Context) string { return randomString(64) }


This section is empty.


type Config

type Config struct {
	// Endpoint is the path which the websocket server will listen for clients/connections
	// Default value is empty string, if you don't set it the Websocket server is disabled.
	Endpoint string
	// ClientSourcePath is is the path which the client-side
	// will be auto-served when the server adapted to an Iris station.
	// Default value is "/iris-ws.js"
	ClientSourcePath string
	Error            func(w http.ResponseWriter, r *http.Request, status int, reason error)
	CheckOrigin      func(r *http.Request) bool
	// WriteTimeout time allowed to write a message to the connection.
	// 0 means no timeout.
	// Default value is 0
	WriteTimeout time.Duration
	// ReadTimeout time allowed to read a message from the connection.
	// 0 means no timeout.
	// Default value is 0
	ReadTimeout time.Duration
	// PongTimeout allowed to read the next pong message from the connection.
	// Default value is 60 * time.Second
	PongTimeout time.Duration
	// PingPeriod send ping messages to the connection with this period. Must be less than PongTimeout.
	// Default value is 60 *time.Second
	PingPeriod time.Duration
	// MaxMessageSize max message size allowed from connection.
	// Default value is 1024
	MaxMessageSize int64
	// BinaryMessages set it to true in order to denotes binary data messages instead of utf-8 text
	// compatible if you wanna use the Connection's EmitMessage to send a custom binary data to the client, like a native server-client communication.
	// defaults to false
	BinaryMessages bool
	// ReadBufferSize is the buffer size for the underline reader
	// Default value is 4096
	ReadBufferSize int
	// WriteBufferSize is the buffer size for the underline writer
	// Default value is 4096
	WriteBufferSize int
	// IDGenerator used to create (and later on, set)
	// an ID for each incoming websocket connections (clients).
	// The request is an argument which you can use to generate the ID (from headers for example).
	// If empty then the ID is generated by DefaultIDGenerator: randomString(64)
	IDGenerator func(ctx context.Context) string

	// Subprotocols specifies the server's supported protocols in order of
	// preference. If this field is set, then the Upgrade method negotiates a
	// subprotocol by selecting the first match in this list with a protocol
	// requested by the client.
	Subprotocols []string

Config the websocket server configuration all of these are optional.

func (Config) Validate

func (c Config) Validate() Config

Validate validates the configuration

type Connection

type Connection interface {
	// Emitter implements EmitMessage & Emit
	// ID returns the connection's identifier
	ID() string

	// Context returns the (upgraded) context.Context of this connection
	// avoid using it, you normally don't need it,
	// websocket has everything you need to authenticate the user BUT if it's necessary
	// then  you use it to receive user information, for example: from headers
	Context() context.Context

	// OnDisconnect registers a callback which fires when this connection is closed by an error or manual
	// OnStatusCode registers a callback which fires when this connection occurs an error
	// FireStatusCode can be used to send a custom error message to the connection
	// It does nothing more than firing the OnStatusCode listeners. It doesn't sends anything to the client.
	FireStatusCode(errorMessage string)
	// To defines where server should send a message
	// returns an emitter to send messages
	To(string) Emitter
	// OnMessage registers a callback which fires when native websocket message received
	// On registers a callback to a particular event which fires when a message to this event received
	On(string, MessageFunc)
	// Join join a connection to a room, it doesn't check if connection is already there, so care
	// Leave removes a connection from a room
	// Returns true if the connection has actually left from the particular room.
	Leave(string) bool
	// OnLeave registers a callback which fires when this connection left from any joined room.
	// This callback is called automatically on Disconnected client, because websocket server automatically
	// deletes the disconnected connection from any joined rooms.
	// Note: the callback(s) called right before the server deletes the connection from the room
	// so the connection theoretical can still send messages to its room right before it is being disconnected.
	OnLeave(roomLeaveCb LeaveRoomFunc)
	// Disconnect disconnects the client, close the underline websocket conn and removes it from the conn list
	// returns the error, if any, from the underline connection
	Disconnect() error
	// SetValue sets a key-value pair on the connection's mem store.
	SetValue(key string, value interface{})
	// GetValue gets a value by its key from the connection's mem store.
	GetValue(key string) interface{}
	// GetValueArrString gets a value as []string by its key from the connection's mem store.
	GetValueArrString(key string) []string
	// GetValueString gets a value as string by its key from the connection's mem store.
	GetValueString(key string) string
	// GetValueInt gets a value as integer by its key from the connection's mem store.
	GetValueInt(key string) int

Connection is the front-end API that you will use to communicate with the client side

type ConnectionFunc

type ConnectionFunc func(Connection)

ConnectionFunc is the callback which fires when a client/connection is connected to the server. Receives one parameter which is the Connection

type ConnectionValues

type ConnectionValues []connectionValue

ConnectionValues is the temporary connection's memory store

func (*ConnectionValues) Get

func (r *ConnectionValues) Get(key string) interface{}

Get returns a value based on its key

func (*ConnectionValues) Reset

func (r *ConnectionValues) Reset()

Reset clears the values

func (*ConnectionValues) Set

func (r *ConnectionValues) Set(key string, value interface{})

Set sets a value based on the key

type DisconnectFunc

type DisconnectFunc func()

DisconnectFunc is the callback which fires when a client/connection closed

type Emitter

type Emitter interface {
	// EmitMessage sends a native websocket message
	EmitMessage([]byte) error
	// Emit sends a message on a particular event
	Emit(string, interface{}) error

Emitter is the message/or/event manager

type ErrorFunc

type ErrorFunc (func(string))

ErrorFunc is the callback which fires when an error happens

type LeaveRoomFunc

type LeaveRoomFunc func(roomName string)

LeaveRoomFunc is the callback which fires when a client/connection leaves from any room. This is called automatically when client/connection disconnected (because websocket server automatically leaves from all joined rooms)

type MessageFunc

type MessageFunc interface{}

MessageFunc is the second argument to the Emitter's Emit functions. A callback which should receives one parameter of type string, int, bool or any valid JSON/Go struct

type NativeMessageFunc

type NativeMessageFunc func([]byte)

NativeMessageFunc is the callback for native websocket messages, receives one []byte parameter which is the raw client's message

type Server

type Server interface {
	// Attach adapts the websocket server to an Iris instance.
	// see websocket.go
	Attach(app *iris.Application)

	// Handler returns the iris.Handler
	// which is setted to the 'Websocket Endpoint path',
	// the client should target to this handler's developer's custom path
	// ex: app.Any("/myendpoint", mywebsocket.Handler())
	Handler() context.Handler

	// OnConnection this is the main event you, as developer, will work with each of the websocket connections
	OnConnection(cb ConnectionFunc)

	// IsConnected returns true if the connection with that ID is connected to the server
	// useful when you have defined a custom connection id generator (based on a database)
	// and you want to check if that connection is already connected (on multiple tabs)
	IsConnected(connID string) bool

	// Join joins a websocket client to a room,
	// first parameter is the room name and the second the connection.ID()
	// You can use connection.Join("room name") instead.
	Join(roomName string, connID string)

	// LeaveAll kicks out a connection from ALL of its joined rooms
	LeaveAll(connID string)

	// Leave leaves a websocket client from a room,
	// first parameter is the room name and the second the connection.ID()
	// You can use connection.Leave("room name") instead.
	// Returns true if the connection has actually left from the particular room.
	Leave(roomName string, connID string) bool

	// GetConnectionsByRoom returns a list of Connection
	// are joined to this room.
	GetConnectionsByRoom(roomName string) []Connection

	// Disconnect force-disconnects a websocket connection
	// based on its connection.ID()
	// What it does?
	// 1. remove the connection from the list
	// 2. leave from all joined rooms
	// 3. fire the disconnect callbacks, if any
	// 4. close the underline connection and return its error, if any.
	// You can use the connection.Disconnect() instead.
	Disconnect(connID string) error

Server is the websocket server, listens on the config's port, the critical part is the event OnConnection

func New

func New(cfg Config) Server

New returns a new websocket server policy adaptor.

type UnderlineConnection

type UnderlineConnection interface {
	// SetWriteDeadline sets the write deadline on the underlying network
	// connection. After a write has timed out, the websocket state is corrupt and
	// all future writes will return an error. A zero value for t means writes will
	// not time out.
	SetWriteDeadline(t time.Time) error
	// SetReadDeadline sets the read deadline on the underlying network connection.
	// After a read has timed out, the websocket connection state is corrupt and
	// all future reads will return an error. A zero value for t means reads will
	// not time out.
	SetReadDeadline(t time.Time) error
	// SetReadLimit sets the maximum size for a message read from the peer. If a
	// message exceeds the limit, the connection sends a close frame to the peer
	// and returns ErrReadLimit to the application.
	SetReadLimit(limit int64)
	// SetPongHandler sets the handler for pong messages received from the peer.
	// The appData argument to h is the PONG frame application data. The default
	// pong handler does nothing.
	SetPongHandler(h func(appData string) error)
	// SetPingHandler sets the handler for ping messages received from the peer.
	// The appData argument to h is the PING frame application data. The default
	// ping handler sends a pong to the peer.
	SetPingHandler(h func(appData string) error)
	// WriteControl writes a control message with the given deadline. The allowed
	// message types are CloseMessage, PingMessage and PongMessage.
	WriteControl(messageType int, data []byte, deadline time.Time) error
	// WriteMessage is a helper method for getting a writer using NextWriter,
	// writing the message and closing the writer.
	WriteMessage(messageType int, data []byte) error
	// ReadMessage is a helper method for getting a reader using NextReader and
	// reading from that reader to a buffer.
	ReadMessage() (messageType int, p []byte, err error)
	// NextWriter returns a writer for the next message to send. The writer's Close
	// method flushes the complete message to the network.
	// There can be at most one open writer on a connection. NextWriter closes the
	// previous writer if the application has not already done so.
	NextWriter(messageType int) (io.WriteCloser, error)
	// Close closes the underlying network connection without sending or waiting for a close frame.
	Close() error

UnderlineConnection is used for compatible with fasthttp and net/http underline websocket libraries we only need ~8 funcs from websocket.Conn so:

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
t or T : Toggle theme light dark auto
y or Y : Canonical URL