diff --git a/doc/api/hooks_server-side.md b/doc/api/hooks_server-side.md index 854b4339..010bc8a3 100644 --- a/doc/api/hooks_server-side.md +++ b/doc/api/hooks_server-side.md @@ -49,7 +49,8 @@ Called from: src/node/server.js Things in context: -1. app - the main application object (helpful for adding new paths and such) +1. app - the main express application object (helpful for adding new paths and such) +2. server - the http server object This hook gets called after the application object has been created, but before it starts listening. This is similar to the expressConfigure hook, but it's not guaranteed that the application object will have all relevant configuration variables. @@ -71,6 +72,7 @@ Things in context: 1. app - the application object 2. io - the socketio object +3. server - the http server object I have no idea what this is useful for, someone else will have to add this description. diff --git a/src/node/hooks/express.js b/src/node/hooks/express.js index 1f4a6f2c..eb3f6188 100644 --- a/src/node/hooks/express.js +++ b/src/node/hooks/express.js @@ -1,4 +1,5 @@ var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks"); +var http = require('http'); var express = require('express'); var settings = require('../utils/Settings'); var fs = require('fs'); @@ -42,22 +43,24 @@ exports.createServer = function () { } exports.restartServer = function () { + if (server) { console.log("Restarting express server"); server.close(); } - server = express.createServer(); + var app = express(); // New syntax for express v3 + server = http.createServer(app); - server.use(function (req, res, next) { + app.use(function (req, res, next) { res.header("Server", serverName); next(); }); - server.configure(function() { - hooks.callAll("expressConfigure", {"app": server}); + app.configure(function() { + hooks.callAll("expressConfigure", {"app": app}); }); - hooks.callAll("expressCreateServer", {"app": server}); + hooks.callAll("expressCreateServer", {"app": app, "server": server}); server.listen(settings.port, settings.ip); -} \ No newline at end of file +} diff --git a/src/node/hooks/express/adminplugins.js b/src/node/hooks/express/adminplugins.js index fc274a07..97a0d602 100644 --- a/src/node/hooks/express/adminplugins.js +++ b/src/node/hooks/express/adminplugins.js @@ -12,14 +12,10 @@ exports.expressCreateServer = function (hook_name, args, cb) { errors: [], }; - res.send(eejs.require( - "ep_etherpad-lite/templates/admin/plugins.html", - render_args), {}); + res.send( eejs.require("ep_etherpad-lite/templates/admin/plugins.html", render_args) ); }); args.app.get('/admin/plugins/info', function(req, res) { - res.send(eejs.require( - "ep_etherpad-lite/templates/admin/plugins-info.html", - {}), {}); + res.send( eejs.require("ep_etherpad-lite/templates/admin/plugins-info.html", {}) ); }); } diff --git a/src/node/hooks/express/errorhandling.js b/src/node/hooks/express/errorhandling.js index 4f5dad4f..3c595683 100644 --- a/src/node/hooks/express/errorhandling.js +++ b/src/node/hooks/express/errorhandling.js @@ -16,9 +16,6 @@ exports.gracefulShutdown = function(err) { console.log("graceful shutdown..."); - //stop the http server - exports.app.close(); - //do the db shutdown db.db.doShutdown(function() { console.log("db sucessfully closed."); @@ -35,10 +32,14 @@ exports.gracefulShutdown = function(err) { exports.expressCreateServer = function (hook_name, args, cb) { exports.app = args.app; - args.app.error(function(err, req, res, next){ - res.send(500); - console.error(err.stack ? err.stack : err.toString()); - }); + // Handle errors + args.app.use(function(err, req, res, next){ + // if an error occurs Connect will pass it down + // through these "error-handling" middleware + // allowing you to respond however you like + res.send(500, { error: 'Sorry, something bad happened!' }); + console.error(err.stack? err.stack : err.toString()); + }) //connect graceful shutdown with sigint and uncaughtexception if(os.type().indexOf("Windows") == -1) { diff --git a/src/node/hooks/express/padreadonly.js b/src/node/hooks/express/padreadonly.js index 60ece0ad..af5cbed3 100644 --- a/src/node/hooks/express/padreadonly.js +++ b/src/node/hooks/express/padreadonly.js @@ -56,7 +56,7 @@ exports.expressCreateServer = function (hook_name, args, cb) { ERR(err); if(err == "notfound") - res.send('404 - Not Found', 404); + res.send(404, '404 - Not Found'); else res.send(html); }); diff --git a/src/node/hooks/express/padurlsanitize.js b/src/node/hooks/express/padurlsanitize.js index 24ec2c3d..29782b69 100644 --- a/src/node/hooks/express/padurlsanitize.js +++ b/src/node/hooks/express/padurlsanitize.js @@ -7,7 +7,7 @@ exports.expressCreateServer = function (hook_name, args, cb) { //ensure the padname is valid and the url doesn't end with a / if(!padManager.isValidPadId(padId) || /\/$/.test(req.url)) { - res.send('Such a padname is forbidden', 404); + res.send(404, 'Such a padname is forbidden'); } else { @@ -19,7 +19,7 @@ exports.expressCreateServer = function (hook_name, args, cb) { var query = url.parse(req.url).query; if ( query ) real_url += '?' + query; res.header('Location', real_url); - res.send('You should be redirected to ' + real_url + '', 302); + res.send(302, 'You should be redirected to ' + real_url + ''); } //the pad id was fine, so just render it else diff --git a/src/node/hooks/express/socketio.js b/src/node/hooks/express/socketio.js index 4f780cb0..546ba2af 100644 --- a/src/node/hooks/express/socketio.js +++ b/src/node/hooks/express/socketio.js @@ -3,6 +3,7 @@ var socketio = require('socket.io'); var settings = require('../../utils/Settings'); 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"); @@ -10,19 +11,28 @@ var connect = require('connect'); exports.expressCreateServer = function (hook_name, args, cb) { //init socket.io and redirect all requests to the MessageHandler - var io = socketio.listen(args.app); + var io = socketio.listen(args.server); /* Require an express session cookie to be present, and load the * session. See http://www.danielbaulig.de/socket-ioexpress for more * info */ io.set('authorization', function (data, accept) { if (!data.headers.cookie) return accept('No session cookie transmitted.', false); - data.cookie = connect.utils.parseCookie(data.headers.cookie); - data.sessionID = data.cookie.express_sid; - args.app.sessionStore.get(data.sessionID, function (err, session) { - if (err || !session) return accept('Bad session / session has expired', false); - data.session = new connect.middleware.session.Session(data, session); - accept(null, true); + + // Use connect's cookie parser, because it knows how to parse signed cookies + connect.cookieParser(webaccess.secret)(data, {}, function(err){ + if(err) { + console.error(err); + accept("Couldn't parse request cookies. ", false); + return; + } + + data.sessionID = data.signedCookies.express_sid; + args.app.sessionStore.get(data.sessionID, function (err, session) { + if (err || !session) return accept('Bad session / session has expired', false); + data.session = new connect.middleware.session.Session(data, session); + accept(null, true); + }); }); }); @@ -62,5 +72,5 @@ exports.expressCreateServer = function (hook_name, args, cb) { socketIORouter.setSocketIO(io); socketIORouter.addComponent("pad", padMessageHandler); - hooks.callAll("socketio", {"app": args.app, "io": io}); + hooks.callAll("socketio", {"app": args.app, "io": io, "server": args.server}); } diff --git a/src/node/hooks/express/webaccess.js b/src/node/hooks/express/webaccess.js index ffced047..41bf3880 100644 --- a/src/node/hooks/express/webaccess.js +++ b/src/node/hooks/express/webaccess.js @@ -56,10 +56,10 @@ exports.basicAuth = function (req, res, next) { res.header('WWW-Authenticate', 'Basic realm="Protected Area"'); if (req.headers.authorization) { setTimeout(function () { - res.send('Authentication required', 401); + res.send(401, 'Authentication required'); }, 1000); } else { - res.send('Authentication required', 401); + res.send(401, 'Authentication required'); } })); } @@ -88,14 +88,13 @@ exports.basicAuth = function (req, res, next) { }); } -var secret = null; +exports.secret = null; exports.expressConfigure = function (hook_name, args, cb) { // 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.INFO, format: ':status, :method :url'})); - args.app.use(express.cookieParser()); /* Do not let express create the session, so that we can retain a * reference to it for socket.io to use. Also, set the key (cookie @@ -104,13 +103,14 @@ exports.expressConfigure = function (hook_name, args, cb) { if (!exports.sessionStore) { exports.sessionStore = new express.session.MemoryStore(); - secret = randomString(32); + exports.secret = randomString(32); } + + args.app.use(express.cookieParser(exports.secret)); args.app.sessionStore = exports.sessionStore; args.app.use(express.session({store: args.app.sessionStore, - key: 'express_sid', - secret: secret})); + key: 'express_sid' })); args.app.use(exports.basicAuth); } diff --git a/src/node/padaccess.js b/src/node/padaccess.js index a3d1df33..4388ab94 100644 --- a/src/node/padaccess.js +++ b/src/node/padaccess.js @@ -15,7 +15,7 @@ module.exports = function (req, res, callback) { callback(); //no access } else { - res.send("403 - Can't touch this", 403); + res.send(403, "403 - Can't touch this"); } }); } diff --git a/src/node/server.js b/src/node/server.js index cca76c1f..b91b0e17 100755 --- a/src/node/server.js +++ b/src/node/server.js @@ -21,8 +21,15 @@ * limitations under the License. */ +// set up logger var log4js = require('log4js'); +log4js.replaceConsole(); + var settings = require('./utils/Settings'); + +//set loglevel +log4js.setGlobalLogLevel(settings.loglevel); + var db = require('./db/DB'); var async = require('async'); var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins"); @@ -31,9 +38,6 @@ var npm = require("npm/lib/npm.js"); hooks.plugins = plugins; -//set loglevel -log4js.setGlobalLogLevel(settings.loglevel); - async.waterfall([ //initalize the database function (callback) diff --git a/src/package.json b/src/package.json index e2f9c774..5f981a7b 100644 --- a/src/package.json +++ b/src/package.json @@ -17,12 +17,12 @@ "socket.io" : "0.9.x", "ueberDB" : "0.1.7", "async" : "0.1.x", - "express" : "2.5.x", - "connect" : "1.x", + "express" : "3.x", + "connect" : "2.4.x", "clean-css" : "0.3.2", "uglify-js" : "1.2.5", "formidable" : "1.0.9", - "log4js" : "0.4.1", + "log4js" : "0.5.x", "jsdom-nocontextifiy" : "0.2.10", "async-stacktrace" : "0.0.2", "npm" : "1.1.24",