mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
Moved theme-specific error handling to frontend
- our themeErrorRenderer is only used in the frontend.. move it there - this required exposing prepareError as shared middleware - TODO: move these shared compontents to @tryghost/error
This commit is contained in:
parent
d7c4168452
commit
ad9eb35746
4 changed files with 99 additions and 88 deletions
93
core/frontend/web/middleware/error-handler.js
Normal file
93
core/frontend/web/middleware/error-handler.js
Normal file
|
@ -0,0 +1,93 @@
|
|||
const hbs = require('express-hbs');
|
||||
const _ = require('lodash');
|
||||
const tpl = require('@tryghost/tpl');
|
||||
const sentry = require('../../../shared/sentry');
|
||||
|
||||
const config = require('../../../shared/config');
|
||||
const helpers = require('../../services/routing/helpers');
|
||||
|
||||
// @TODO: make this properly shared code
|
||||
const shared = require('../../../server/web/shared/middleware/error-handler');
|
||||
|
||||
const messages = {
|
||||
oopsErrorTemplateHasError: 'Oops, seems there is an error in the error template.',
|
||||
encounteredError: 'Encountered the error: ',
|
||||
whilstTryingToRender: 'whilst trying to render an error page for the error: '
|
||||
};
|
||||
|
||||
const escapeExpression = hbs.Utils.escapeExpression;
|
||||
|
||||
/**
|
||||
* This is a bare minimum setup, which allows us to render the error page
|
||||
* It uses the {{asset}} helper, and nothing more
|
||||
*/
|
||||
const createHbsEngine = () => {
|
||||
const engine = hbs.create();
|
||||
engine.registerHelper('asset', require('../../helpers/asset'));
|
||||
|
||||
return engine.express4();
|
||||
};
|
||||
|
||||
const errorFallbackMessage = err => `<h1>${tpl(messages.oopsErrorTemplateHasError)}</h1>
|
||||
<p>${tpl(messages.encounteredError)}</p>
|
||||
<pre>${escapeExpression(err.message || err)}</pre>
|
||||
<br ><p>${tpl(messages.whilstTryingToRender)}</p>
|
||||
${err.statusCode} <pre>${escapeExpression(err.message || err)}</pre>`;
|
||||
|
||||
const themeErrorRenderer = (err, req, res, next) => {
|
||||
// If the error code is explicitly set to STATIC_FILE_NOT_FOUND,
|
||||
// Skip trying to render an HTML error, and move on to the basic error renderer
|
||||
// We do this because customised 404 templates could reference the image that's missing
|
||||
// A better long term solution might be to do this based on extension
|
||||
if (err.code === 'STATIC_FILE_NOT_FOUND') {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
// Renderer begin
|
||||
// Format Data
|
||||
const data = {
|
||||
message: err.message,
|
||||
// @deprecated Remove in Ghost 5.0
|
||||
code: err.statusCode,
|
||||
statusCode: err.statusCode,
|
||||
errorDetails: err.errorDetails || []
|
||||
};
|
||||
|
||||
// Template
|
||||
// @TODO: very dirty !!!!!!
|
||||
helpers.templates.setTemplate(req, res);
|
||||
|
||||
// It can be that something went wrong with the theme or otherwise loading handlebars
|
||||
// This ensures that no matter what res.render will work here
|
||||
// @TODO: split the error handler for assets, admin & theme to refactor this away
|
||||
if (_.isEmpty(req.app.engines)) {
|
||||
res._template = 'error';
|
||||
req.app.engine('hbs', createHbsEngine());
|
||||
req.app.set('view engine', 'hbs');
|
||||
req.app.set('views', config.get('paths').defaultViews);
|
||||
}
|
||||
|
||||
// @TODO use renderer here?!
|
||||
// Render Call - featuring an error handler for what happens if rendering fails
|
||||
res.render(res._template, data, (_err, html) => {
|
||||
if (!_err) {
|
||||
return res.send(html);
|
||||
}
|
||||
|
||||
// re-attach new error e.g. error template has syntax error or misusage
|
||||
req.err = _err;
|
||||
|
||||
// And then try to explain things to the user...
|
||||
// Cheat and output the error using handlebars escapeExpression
|
||||
return res.status(500).send(errorFallbackMessage(_err));
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.handleThemeResponse = [
|
||||
// Make sure the error can be served
|
||||
shared.prepareError,
|
||||
// Handle the error in Sentry
|
||||
sentry.errorHandler,
|
||||
// Render the error using theme template
|
||||
themeErrorRenderer
|
||||
];
|
|
@ -1,4 +1,5 @@
|
|||
module.exports = {
|
||||
errorHandler: require('./error-handler'),
|
||||
handleImageSizes: require('./handle-image-sizes'),
|
||||
redirectGhostToAdmin: require('./redirect-ghost-to-admin'),
|
||||
serveFavicon: require('./serve-favicon'),
|
||||
|
|
|
@ -184,7 +184,7 @@ module.exports = function setupSiteApp(options = {}) {
|
|||
app.setupErrorHandling(siteApp);
|
||||
}
|
||||
});
|
||||
siteApp.use(shared.middleware.errorHandler.handleThemeResponse);
|
||||
siteApp.use(mw.errorHandler.handleThemeResponse);
|
||||
|
||||
debug('Site setup end');
|
||||
|
||||
|
|
|
@ -1,16 +1,10 @@
|
|||
const hbs = require('express-hbs');
|
||||
const _ = require('lodash');
|
||||
const debug = require('@tryghost/debug')('error-handler');
|
||||
const errors = require('@tryghost/errors');
|
||||
const tpl = require('@tryghost/tpl');
|
||||
const config = require('../../../../shared/config');
|
||||
const helpers = require('../../../../frontend/services/routing/helpers');
|
||||
const sentry = require('../../../../shared/sentry');
|
||||
|
||||
const messages = {
|
||||
oopsErrorTemplateHasError: 'Oops, seems there is an error in the error template.',
|
||||
encounteredError: 'Encountered the error: ',
|
||||
whilstTryingToRender: 'whilst trying to render an error page for the error: ',
|
||||
pageNotFound: 'Page not found',
|
||||
resourceNotFound: 'Resource not found',
|
||||
actions: {
|
||||
|
@ -45,19 +39,6 @@ const messages = {
|
|||
}
|
||||
};
|
||||
|
||||
const escapeExpression = hbs.Utils.escapeExpression;
|
||||
|
||||
/**
|
||||
* This is a bare minimum setup, which allows us to render the error page
|
||||
* It uses the {{asset}} helper, and nothing more
|
||||
*/
|
||||
const createHbsEngine = () => {
|
||||
const engine = hbs.create();
|
||||
engine.registerHelper('asset', require('../../../../frontend/helpers/asset'));
|
||||
|
||||
return engine.express4();
|
||||
};
|
||||
|
||||
const updateStack = (err) => {
|
||||
let stackbits = err.stack.split(/\n/g);
|
||||
|
||||
|
@ -87,7 +68,7 @@ const updateStack = (err) => {
|
|||
/**
|
||||
* Get an error ready to be shown the the user
|
||||
*/
|
||||
const prepareError = (err, req, res, next) => {
|
||||
module.exports.prepareError = (err, req, res, next) => {
|
||||
debug(err);
|
||||
|
||||
if (Array.isArray(err)) {
|
||||
|
@ -201,61 +182,6 @@ const prepareUserMessage = (err, res) => {
|
|||
return userError;
|
||||
};
|
||||
|
||||
const errorFallbackMessage = err => `<h1>${tpl(messages.oopsErrorTemplateHasError)}</h1>
|
||||
<p>${tpl(messages.encounteredError)}</p>
|
||||
<pre>${escapeExpression(err.message || err)}</pre>
|
||||
<br ><p>${tpl(messages.whilstTryingToRender)}</p>
|
||||
${err.statusCode} <pre>${escapeExpression(err.message || err)}</pre>`;
|
||||
|
||||
const themeErrorRenderer = (err, req, res, next) => {
|
||||
// If the error code is explicitly set to STATIC_FILE_NOT_FOUND,
|
||||
// Skip trying to render an HTML error, and move on to the basic error renderer
|
||||
// We do this because customised 404 templates could reference the image that's missing
|
||||
// A better long term solution might be to do this based on extension
|
||||
if (err.code === 'STATIC_FILE_NOT_FOUND') {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
// Renderer begin
|
||||
// Format Data
|
||||
const data = {
|
||||
message: err.message,
|
||||
// @deprecated Remove in Ghost 5.0
|
||||
code: err.statusCode,
|
||||
statusCode: err.statusCode,
|
||||
errorDetails: err.errorDetails || []
|
||||
};
|
||||
|
||||
// Template
|
||||
// @TODO: very dirty !!!!!!
|
||||
helpers.templates.setTemplate(req, res);
|
||||
|
||||
// It can be that something went wrong with the theme or otherwise loading handlebars
|
||||
// This ensures that no matter what res.render will work here
|
||||
// @TODO: split the error handler for assets, admin & theme to refactor this away
|
||||
if (_.isEmpty(req.app.engines)) {
|
||||
res._template = 'error';
|
||||
req.app.engine('hbs', createHbsEngine());
|
||||
req.app.set('view engine', 'hbs');
|
||||
req.app.set('views', config.get('paths').defaultViews);
|
||||
}
|
||||
|
||||
// @TODO use renderer here?!
|
||||
// Render Call - featuring an error handler for what happens if rendering fails
|
||||
res.render(res._template, data, (_err, html) => {
|
||||
if (!_err) {
|
||||
return res.send(html);
|
||||
}
|
||||
|
||||
// re-attach new error e.g. error template has syntax error or misusage
|
||||
req.err = _err;
|
||||
|
||||
// And then try to explain things to the user...
|
||||
// Cheat and output the error using handlebars escapeExpression
|
||||
return res.status(500).send(errorFallbackMessage(_err));
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.resourceNotFound = (req, res, next) => {
|
||||
next(new errors.NotFoundError({message: tpl(messages.resourceNotFound)}));
|
||||
};
|
||||
|
@ -266,7 +192,7 @@ module.exports.pageNotFound = (req, res, next) => {
|
|||
|
||||
module.exports.handleJSONResponse = [
|
||||
// Make sure the error can be served
|
||||
prepareError,
|
||||
module.exports.prepareError,
|
||||
// Handle the error in Sentry
|
||||
sentry.errorHandler,
|
||||
// Render the error using JSON format
|
||||
|
@ -275,7 +201,7 @@ module.exports.handleJSONResponse = [
|
|||
|
||||
module.exports.handleJSONResponseV2 = [
|
||||
// Make sure the error can be served
|
||||
prepareError,
|
||||
module.exports.prepareError,
|
||||
// Handle the error in Sentry
|
||||
sentry.errorHandler,
|
||||
// Render the error using JSON format
|
||||
|
@ -284,16 +210,7 @@ module.exports.handleJSONResponseV2 = [
|
|||
|
||||
module.exports.handleHTMLResponse = [
|
||||
// Make sure the error can be served
|
||||
prepareError,
|
||||
module.exports.prepareError,
|
||||
// Handle the error in Sentry
|
||||
sentry.errorHandler
|
||||
];
|
||||
|
||||
module.exports.handleThemeResponse = [
|
||||
// Make sure the error can be served
|
||||
prepareError,
|
||||
// Handle the error in Sentry
|
||||
sentry.errorHandler,
|
||||
// Render the error using theme template
|
||||
themeErrorRenderer
|
||||
];
|
||||
|
|
Loading…
Add table
Reference in a new issue