pr-express-server
Version:
ExpressJS based server with useful middlewares
143 lines (131 loc) • 4.03 kB
JavaScript
;
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;