GCSBOSS/nodecaf

View on GitHub
lib/ws.js

Summary

Maintainability
A
0 mins
Test Coverage
const cookie = require('./cookie');
const { WebSocketServer } = require('ws');
const normalizePath = p => (p.slice(-1) == '/' ? p.slice(0, -1) : p) || '/';

function checkClientsHealth(){
    // this => wss
    this.clients.forEach(function(ws) {
        if(ws.isAlive === false)
            return ws.terminate();
        ws.isAlive = false;
        ws.ping();
    });
}

function onUpgrade(req, socket, head){
    // this => app

    const connect = () => new Promise(done => {
        this._wss.handleUpgrade(req, socket, head, ws => {
            ws.isAlive = true;
            ws.on('pong', () => ws.isAlive = true);
            done(ws);
        });
    });

    const { ServerResponse } = require('http');
    const res = new ServerResponse(req);
    const [ path, query ] = req.url.split('?');

    this._api.trigger(req.method, normalizePath(path), {
        body: req, res, websocket: connect, headers: req.headers,
        query: Object.fromEntries(new URLSearchParams(query).entries()),
        cookies: cookie.parse(req.headers.cookie || '')
    });
}

function buildWebSocketServer(app){
    const wss = new WebSocketServer({ noServer: true });

    const interval = setInterval(checkClientsHealth.bind(wss), 30000);

    app._server.on('close', function() {
        clearInterval(interval);
        wss.clients.forEach(ws => ws.terminate());
    });

    app._server.on('upgrade', onUpgrade.bind(app));

    return wss;
}

module.exports = { buildWebSocketServer };