diff --git a/src/node/hooks/express.js b/src/node/hooks/express.js index 5363d331e..9bb4f2239 100644 --- a/src/node/hooks/express.js +++ b/src/node/hooks/express.js @@ -1,12 +1,18 @@ const _ = require('underscore'); +const cookieParser = require('cookie-parser'); const express = require('express'); +const expressSession = require('express-session'); const fs = require('fs'); const hooks = require('../../static/js/pluginfw/hooks'); +const log4js = require('log4js'); const npm = require('npm/lib/npm'); const path = require('path'); +const sessionStore = require('../db/SessionStore'); const settings = require('../utils/Settings'); +const stats = require('../stats'); const util = require('util'); +const logger = log4js.getLogger('http'); let serverName; exports.server = null; @@ -111,6 +117,60 @@ exports.restartServer = async () => { app.enable('trust proxy'); } + // Measure response time + app.use((req, res, next) => { + const stopWatch = stats.timer('httpRequests').start(); + const sendFn = res.send.bind(res); + res.send = (...args) => { stopWatch.end(); sendFn(...args); }; + next(); + }); + + // If the log level specified in the config file is WARN or ERROR the application server never + // starts listening to requests as reported in issue #158. Not installing the log4js connect + // logger when the log level has a higher severity than INFO since it would not log at that level + // anyway. + if (!(settings.loglevel === 'WARN' && settings.loglevel === 'ERROR')) { + app.use(log4js.connectLogger(logger, { + level: log4js.levels.DEBUG, + format: ':status, :method :url', + })); + } + + exports.sessionMiddleware = expressSession({ + secret: settings.sessionKey, + store: new sessionStore(), + resave: false, + saveUninitialized: true, + // Set the cookie name to a javascript identifier compatible string. Makes code handling it + // cleaner :) + name: 'express_sid', + proxy: true, + cookie: { + sameSite: settings.cookie.sameSite, + + // The automatic express-session mechanism for determining if the application is being served + // over ssl is similar to the one used for setting the language cookie, which check if one of + // these conditions is true: + // + // 1. we are directly serving the nodejs application over SSL, using the "ssl" options in + // settings.json + // + // 2. we are serving the nodejs application in plaintext, but we are using a reverse proxy + // that terminates SSL for us. In this case, the user has to set trustProxy = true in + // settings.json, and the information wheter the application is over SSL or not will be + // extracted from the X-Forwarded-Proto HTTP header + // + // Please note that this will not be compatible with applications being served over http and + // https at the same time. + // + // reference: https://github.com/expressjs/session/blob/v1.17.0/README.md#cookiesecure + secure: 'auto', + } + }); + app.use(exports.sessionMiddleware); + + app.use(cookieParser(settings.sessionKey, {})); + hooks.callAll("expressConfigure", {"app": app}); hooks.callAll('expressCreateServer', {app, server: exports.server}); diff --git a/src/node/hooks/express/socketio.js b/src/node/hooks/express/socketio.js index 3ceae1ddc..f5964f18a 100644 --- a/src/node/hooks/express/socketio.js +++ b/src/node/hooks/express/socketio.js @@ -1,8 +1,8 @@ +const express = require("../express"); var settings = require('../../utils/Settings'); var socketio = require('socket.io'); var socketIORouter = require("../../handler/SocketIORouter"); var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks"); -var webaccess = require("ep_etherpad-lite/node/hooks/express/webaccess"); var padMessageHandler = require("../../handler/PadMessageHandler"); @@ -44,7 +44,7 @@ exports.expressCreateServer = function (hook_name, args, cb) { req.headers.cookie = socket.handshake.query.cookie; } // See: https://socket.io/docs/faq/#Usage-with-express-session - webaccess.sessionMiddleware(req, {}, next); + express.sessionMiddleware(req, {}, next); }); // var socketIOLogger = log4js.getLogger("socket.io"); diff --git a/src/node/hooks/express/webaccess.js b/src/node/hooks/express/webaccess.js index 843cf1478..64943dda3 100644 --- a/src/node/hooks/express/webaccess.js +++ b/src/node/hooks/express/webaccess.js @@ -1,13 +1,8 @@ const assert = require('assert').strict; -const express = require('express'); const log4js = require('log4js'); const httpLogger = log4js.getLogger('http'); const settings = require('../../utils/Settings'); const hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks'); -const ueberStore = require('../../db/SessionStore'); -const stats = require('ep_etherpad-lite/node/stats'); -const sessionModule = require('express-session'); -const cookieParser = require('cookie-parser'); hooks.deprecationNotices.authFailure = 'use the authnFailure and authzFailure hooks instead'; @@ -200,62 +195,5 @@ exports.checkAccess = (req, res, next) => { }; exports.expressConfigure = (hook_name, args, cb) => { - // Measure response time - args.app.use((req, res, next) => { - const stopWatch = stats.timer('httpRequests').start(); - const sendFn = res.send.bind(res); - res.send = (...args) => { stopWatch.end(); sendFn(...args); }; - next(); - }); - - // If the log level specified in the config file is WARN or ERROR the application server never - // starts listening to requests as reported in issue #158. Not installing the log4js connect - // logger when the log level has a higher severity than INFO since it would not log at that level - // anyway. - if (!(settings.loglevel === 'WARN' && settings.loglevel === 'ERROR')) { - args.app.use(log4js.connectLogger(httpLogger, { - level: log4js.levels.DEBUG, - format: ':status, :method :url', - })); - } - - exports.sessionMiddleware = sessionModule({ - secret: settings.sessionKey, - store: new ueberStore(), - resave: false, - saveUninitialized: true, - // Set the cookie name to a javascript identifier compatible string. Makes code handling it - // cleaner :) - name: 'express_sid', - proxy: true, - cookie: { - sameSite: settings.cookie.sameSite, - /* - * The automatic express-session mechanism for determining if the - * application is being served over ssl is similar to the one used for - * setting the language cookie, which check if one of these conditions is - * true: - * - * 1. we are directly serving the nodejs application over SSL, using the - * "ssl" options in settings.json - * - * 2. we are serving the nodejs application in plaintext, but we are using - * a reverse proxy that terminates SSL for us. In this case, the user - * has to set trustProxy = true in settings.json, and the information - * wheter the application is over SSL or not will be extracted from the - * X-Forwarded-Proto HTTP header - * - * Please note that this will not be compatible with applications being - * served over http and https at the same time. - * - * reference: https://github.com/expressjs/session/blob/v1.17.0/README.md#cookiesecure - */ - secure: 'auto', - } - }); - args.app.use(exports.sessionMiddleware); - - args.app.use(cookieParser(settings.sessionKey, {})); - args.app.use(exports.checkAccess); };