diff --git a/core/server.js b/core/server.js index 168f682817..94fddce818 100644 --- a/core/server.js +++ b/core/server.js @@ -277,12 +277,19 @@ when.all([ghost.init(), helpers.loadCoreHelpers(ghost)]).then(function () { server.use(server.router); // ### Error handling - // TODO: replace with proper 400 and 500 error pages - // 404's - server.use(function error404Handler(req, res, next) { - console.log('test', req.url); - next(); - //res.send(404, {message: "Page not found"}); + // 404 Handler + server.use(errors.render404Page); + + // TODO: Handle all application errors (~500) + // Just stubbed at this stage! + server.use(function error500Handler(err, req, res, next) { + if (!err || !(err instanceof Error)) { + next(); + } + + // For the time being, just log and continue. + errors.logError(err, "Middleware", "Ghost caught a processing error in the middleware layer."); + next(err); }); // All other errors diff --git a/core/server/errorHandling.js b/core/server/errorHandling.js index 41d4b895d4..bf6c9661b0 100644 --- a/core/server/errorHandling.js +++ b/core/server/errorHandling.js @@ -1,6 +1,14 @@ var _ = require('underscore'), colors = require("colors"), - errors; + fs = require('fs'), + path = require('path'), + errors, + + // Paths for views + appRoot = path.resolve(__dirname, '../'), + themePath = path.resolve(appRoot + '/content/themes'), + userErrorTemplatePath = path.resolve(themePath + '/error.hbs'), + userErrorTemplateExists; /** * Basic error handling helpers @@ -21,7 +29,7 @@ errors = { logError: function (err, context, help) { err = err.message || err || "Unknown"; // TODO: Logging framework hookup -// Eventually we'll have better logging which will know about envs + // Eventually we'll have better logging which will know about envs if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'staging' || process.env.NODE_ENV === 'production') { @@ -61,10 +69,69 @@ errors = { res.redirect(redirectTo); } }; + }, + + renderErrorPage: function (code, err, req, res, next) { + // Render the error! + function renderErrorInt() { + // TODO: Attach node-polyglot + res.render('error', { + message: err.message || err, + code: code + }); + } + + if (code >= 500) { + this.logError(err, "ErrorPage"); + } + + // Are we admin? If so, don't worry about the user template + if (res.isAdmin) { + return renderErrorInt(); + } + + if (userErrorTemplateExists === false) { + return next(); + } + + if (userErrorTemplateExists === true) { + return renderErrorInt(); + } + + // userErrorTemplateExists is undefined, which means we + // haven't yet checked for it. Do so now! + fs.stat(userErrorTemplatePath, function (err, stat) { + userErrorTemplateExists = !err; + if (userErrorTemplateExists) { + return renderErrorInt(); + } + + // Message only displays the first time an error is triggered. + errors.logError( + "Theme error template not found", + null, + "Add an error.hbs template to the theme for customised errors." + ); + + next(); + }); + }, + + render404Page: function (req, res, next) { + var message = res.isAdmin ? "No Ghost Found" : "Resource Not Found"; + this.renderErrorPage(404, message, req, res, next); } }; // Ensure our 'this' context in the functions -_.bindAll(errors, "throwError", "logError", "logAndThrowError", "logErrorWithRedirect"); +_.bindAll( + errors, + "throwError", + "logError", + "logAndThrowError", + "logErrorWithRedirect", + "renderErrorPage", + "render404Page" +); module.exports = errors; \ No newline at end of file diff --git a/core/server/views/error.hbs b/core/server/views/error.hbs new file mode 100644 index 0000000000..5f3ef04f4a --- /dev/null +++ b/core/server/views/error.hbs @@ -0,0 +1,10 @@ +{{!< default}} +
+
+ +
+
+

{{code}}

+

{{message}}

+
+
\ No newline at end of file