Snub-WS
Middleware WS server that allows you to run web-sockets over snub.
Usage
npm install snub
npm install snub-ws
Basic Example
With redis installed and running with default port and no auth.
const Snub = require('snub');
const snub = new Snub();
const SnubWS = require('snub-ws');
const snubws = new SnubWS(
debug: true
);
snub.use(snubws);
Config options
{
port: 8585, // Web-socket server port
debug: true, // Bool, turns on verbose messaging.
mutliLogin: true, // Bool, can the same username connection more than once?
auth: 'auth-event', // String OR Function OR bool for no auth required
authTimeout: 3000, // how long to wait for the client to auth before disconnecting
throttle: [50, 5000], // X number of messages per Y milliseconds before disconnecting
idleTimeout: 1000 * 60 * 60, // how long can an idle client be connected
}
Auth Config extra
auth can be passed 1 of 3 things
Function
A function passed to auth
{
auth: function (auth, accept) {
if (auth.username == 'username')
return accept(true); // run accept to authenticate the web-socket client connection.
accept(false); // run with false to decline the web-socket connection and disconnect the client.
}
}
Snub event
{
auth: 'authenticate-client';
}
snub.on('ws:authenticate-client', function (auth, accept) {
// console.log(auth);
if (auth.username == 'username') return accept(true);
reply(false);
});
TODO docs
False for no auth
Authenticating a client
The first thing a client should do after connecting is send an authenitication message. username is required, the entire object will be passed to your authentication method.
['_auth', { username, password}];
Sending messages from the client
Web socket message objects should be JSON stringified arrays. The first item is always the event name followed by payload, followed by the replyId. Only event name is required.
['event-name', { payload }, replyId];
String
A string passed to auth will run the method as a snub event. Reply true or false.
{
auth: 'authenticate-client';
}
snub.on('ws:authenticate-client', function (auth, reply) {
console.log(auth);
if (auth.username == 'username') return reply(true);
reply(false);
});
Boolean
A bool with false will authenticate any web-socket client connection.
{
auth: false;
}
Events
Client > Server
When a client sends data to the server the event will be prefixed with ws:
{
from: { // client socket info
id: '89668-mnm4i6', // unique uuid generated by snub-ws
username: 'username', // defined in auth
channels: [], // clients channel list
connected: true, // connection status
authenticated: true, // auth status
connectTime: 1583803891546, // timestamp
remoteAddress: '::1', // clients ip address
meta: {} // client meta obj
},
payload: {}, // payload from client
_ts: 1583803922264 // timestamp
}
Simple snub listener. inbound messages from client will be prefixed with ws:
snub.on('ws:do-math', function (event, reply) {
console.log('domath');
reply(event.payload * 10);
});
Server > Client
Send event to all clients
snub.poly('ws:send-all', ['event-name', { payload }]).send();
Send event to channel
snub.poly('ws:send-channel:' + 'channel6', ['event-name', { payload }]).send();
Send event to multiple channels
snub
.poly('ws:send-channel:' + ['channel6', 'channel2', 'channel3'].join(','), [
'event-name',
{ payload },
])
.send();
Send event to client
snub.poly('ws:send:' + 'username', ['event-name', { payload }]).send();
// or
snub.poly('ws:send:' + event.from.id, ['event-name', { payload }]).send();
Send event to multiple clients
snub
.poly('ws:send-some, [
'event-name',
['user1', 'user2', 'user3']
{ payload },
])
.send();
// use this only for a small amount of users.
snub
.poly('ws:send:' + ['user1', 'user2', 'user3'].join(','), [
'event-name',
{ payload },
])
.send();
Channels
snub.poly('ws:add-channel:' + 'username', ['channel1', 'channel2']).send(); // add to existing channels
snub.poly('ws:set-channel:' + 'username', ['channel1', 'channel2']).send(); // wipes and sets channels
snub.poly('ws:del-channel:' + 'username', ['channel1', 'channel2']).send(); // removes channels
// send to channel
snub.poly('ws:send-channel:' + 'channel6', ['event-name', { payload }]).send();
Meta
You can set meta against a client, which will be availbe in the event.from.meta object
snub.poly('ws:set-meta:' + 'username', { prop1: 'AOK' }).send();
snub
.mono('ws:get-clients:' + 'usernameOrId')
.replyAt((clients) => {
// clients = Array of client states Inludes client.meta
})
.send();
WS Client emitted events
ws:connected-clients-update
will be poly emitted when client connects or client state changes.
ws:connected-clients-update
mono emitted as above
ws:connected-clients-offline
will be poly emitted with client state as payload when client disconects
ws:connected-clients-offline-mono
mono emitted event as above