Skip to content

Instantly share code, notes, and snippets.

@inorganik
Created July 12, 2019 17:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save inorganik/b3485337f0a50077d3fd8b19d8cfbc06 to your computer and use it in GitHub Desktop.
Save inorganik/b3485337f0a50077d3fd8b19d8cfbc06 to your computer and use it in GitHub Desktop.
An abstract websocket endpoint class for node express
import * as expressWs from 'express-ws';
import * as WebSocket from 'ws';
/**
* Extend this class to make a new WebSocket endpoint.
*
* Derived classes should pass an Express app object and the
* string endpoint, and must implement handleMessage()
*/
export abstract class WebSocketMock {
msgIntervalRef; // setInterval reference for streaming simulation
msgInterval = 2500; // amount of time between messages
maxMsgs = 48; // stop interval after this many
private msgsSent = 0;
private pingPongIntervalRef; // for checking if connection is alive
private pingPongInterval = 10000; // check connection at this interval
constructor(app: any, private endpoint: string) {
expressWs(app);
app.ws(this.endpoint, this.handleStreamRequest.bind(this));
}
abstract handleMessage(parsedRequest: any, count: number): any;
static randomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
handleStreamRequest(ws: WebSocket) {
console.log(`new connection to ${this.endpoint}`);
const closeConnection = () => {
console.log(`lost connection to ${this.endpoint}, closing`);
clearInterval(this.pingPongIntervalRef);
clearInterval(this.msgIntervalRef);
ws.terminate();
};
const sendObject = (obj: any) => {
// make sure ws exists otherwise clear intervals
try {
ws.send(JSON.stringify(obj));
} catch (error) {
closeConnection();
}
};
// monitor connection and close if client disconnects
ws.isAlive = true;
clearInterval(this.pingPongIntervalRef);
this.pingPongIntervalRef = setInterval(() => {
if (ws && ws.isAlive) {
ws.isAlive = false;
ws.ping(() => null); // cb must be defined
} else {
closeConnection();
}
}, this.pingPongInterval);
ws.on('pong', () => (ws.isAlive = true));
// handle client post, send response
ws.on('message', (msg) => {
clearInterval(this.msgIntervalRef);
this.msgsSent = 0;
const payload = JSON.parse(msg);
// send initial
sendObject(this.handleMessage(payload, this.msgsSent));
this.msgsSent++;
// simulate streaming messages
this.msgIntervalRef = setInterval(() => {
if (this.msgsSent >= this.maxMsgs) {
clearInterval(this.msgIntervalRef);
} else {
sendObject(this.handleMessage(payload, this.msgsSent));
this.msgsSent++;
}
}, this.msgInterval);
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment