UNPKG

pr-express-server

Version:

ExpressJS based server with useful middlewares

143 lines (131 loc) 4.03 kB
"use strict"; var http = require("http"), express = require("express"), toobusy = require("toobusy-js"), expressWinston = require("express-winston"), compression = require("compression"), expressBodyParser = require("pr-express-body-parser"), ws = require("ws"), expressWs = require("pr-express-ws"), WsMonitor = require("pr-ws-monitor"), redisCookieSession = require("pr-express-redis-session"), helmet = require("helmet"), defaults = require("./defaults"); function getOptions(options) { var opts = options || {}; opts = Object.assign.apply(null, Object.keys(defaults).map(prop => ({ [prop]: opts[prop] }))); Object.keys(defaults).forEach(function each(o) { opts[o] = opts[o] || defaults[o]; }); return opts; } function setupMiddlewares(app, opts) { // eslint-disable-line max-statements // HTTP req/res logger if (opts.winstonHttpLogger) { app.use(expressWinston.logger(opts.winstonHttpLogger)); } // toobusy if (opts.toobusy) { if (opts.toobusy.maxLag) { toobusy.maxLag(opts.toobusy.maxLag); } if (opts.toobusy.interval) { toobusy.interval(opts.toobusy.interval); } app.use(function toobusyMiddleware(req, res, next) { var err; if (toobusy()) { err = new Error("Node event-loop too-busy"); err.status = 503; next(err); } else { next(); } }); } // request ID if (opts.requestID) { app.use(function requestIdMiddleware(req, res, next) { req[opts.requestID.key] = opts.requestID.generator(); next(); }); } // request logger if (opts.requestLogger) { app.use(function requestLoggerMiddleware(req, res, next) { var context = {}; if (opts.requestID) { context[opts.requestID.key] = req[opts.requestID.key]; } req[opts.requestLogger.key] = opts.requestLogger.logger.child(context); next(); }); } // compression if (opts.compression) { app.use(compression(opts.compression)); } // body parsing if (opts.bodyParser) { app.use(expressBodyParser(opts.bodyParser)); } // helmet if (opts.helmet) { Object.keys(opts.helmet).forEach(function each(op) { if (opts.helmet[op]) { app.use(helmet[op](opts.helmet[op])); } }); } // redis session if (opts.redisCookieSession) { app.use(redisCookieSession(opts.redisCookieSession.redisConfig, opts.redisCookieSession.sessionConfig)); } } function createServer(options) { var httpServer, wss, wsMon, opts = getOptions(options), app = express(); // setup middlewares setupMiddlewares(app, opts); // start server app.listen = function listen(callback) { // setup http-server httpServer = http.createServer(app); if (opts.expressWs) { wss = new ws.Server({ "noServer": true, "clientTracking": true }); httpServer.on("upgrade", expressWs.handleWebsocketUpgrade(app, wss)); wsMon = new WsMonitor(wss, opts.wsMonitor); wsMon.start(); } if (callback) { httpServer.once("listening", function onListening() { callback(); }); } httpServer.listen(opts.port); }; // stop server app.close = function close(callback) { if (callback) { httpServer.once("close", function onClose() { callback(); }); } toobusy.shutdown(); wsMon.stop(); wss.close(function onWsClose() { httpServer.close(); }); }; return app; } createServer(); // exports module.exports = createServer;