const http = require('http') const WebSocket = require('ws') const finalHttpHandler = require('finalhandler') const serveStatic = require('serve-static') const logger = require('./logger') function getRemoteAddr (req) { return req.headers['cf-connecting-ip'] || req.headers['x-forwarded-for'] || req.connection.remoteAddress } class Server { constructor (clientSocketHandler) { this.createHttpServer() this.createWebSocketServer(clientSocketHandler) } createHttpServer () { const distServeStatic = serveStatic('dist/') const faviconsServeStatic = serveStatic('favicons/') this._http = http.createServer((req, res) => { logger.log('info', '%s requested: %s', getRemoteAddr(req), req.url) // Attempt to handle req using distServeStatic, otherwise fail over to faviconServeStatic // If faviconServeStatic fails, pass to finalHttpHandler to terminate distServeStatic(req, res, () => { faviconsServeStatic(req, res, finalHttpHandler(req, res)) }) }) } createWebSocketServer (proxyClientSocketHandler) { this._wss = new WebSocket.Server({ server: this._http }) this._wss.on('connection', (client, req) => { logger.log('info', '%s connected, total clients: %d', getRemoteAddr(req), this.getConnectedClients()) // Bind disconnect event for logging client.on('close', () => { logger.log('info', '%s disconnected, total clients: %d', getRemoteAddr(req), this.getConnectedClients()) }) // Pass client off to proxy handler proxyClientSocketHandler(client) }) } listen (host, port) { this._http.listen(port, host) logger.log('info', 'Started on %s:%d', host, port) } broadcast (payload) { this._wss.clients.forEach(client => { if (client.readyState === WebSocket.OPEN) { client.send(payload) } }) } getConnectedClients () { let count = 0 this._wss.clients.forEach(client => { if (client.readyState === WebSocket.OPEN) { count++ } }) return count } } module.exports = Server