Skip to content

Instantly share code, notes, and snippets.

@ekryski
Last active December 11, 2015 11:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ekryski/4596191 to your computer and use it in GitHub Desktop.
Save ekryski/4596191 to your computer and use it in GitHub Desktop.
Express Error Handler
app.configure( 'development', function () {
app.use( express.logger( {format: 'dev'} ) );
app.use( express.static( __dirname + '/public' ) );
app.use( errorHandler( { dumpExceptions: true, showStack: true } ) );
} );
/**
* App Error Object
*
* An error abject that extends Error to accomodate status codes.
*
* @param {Object} message
* @param {Object} status
* @param {Object} status
* @api pubic
*/
var _underscore = require('underscore');
function ServerError(message, status, options){
options = options || {};
this.name = options.name || 'Error';
this.message = message || options.message || 'Internal Server Error';
this.status = status || options.status || 500;
//Convert to string if message is an array
if (_underscore.isArray(this.message)) {
this.message = this.message.join(', ');
}
Error.call(this, this.name);
Error.captureStackTrace(this, arguments.callee);
}
ServerError.prototype.__proto__ = Error.prototype;
module.exports = ServerError;
/*!
* Connect - errorHandler
* Copyright(c) 2010 Sencha Inc.
* Copyright(c) 2011 TJ Holowaychuk
* Copyright(c) 2011 Eric Kryski
* MIT Licensed
*/
/**
* Flexible error handler, providing (_optional_) stack traces
* and error message responses for requests accepting text, html,
* or json.
*
* Options:
*
* - `showStack`, `stack` respond with both the error message and stack trace. Defaults to `false`
* - `showMessage`, `message`, respond with the exception message only. Defaults to `false`
* - `dumpExceptions`, `dump`, dump exceptions to stderr (without terminating the process). Defaults to `false`
*
* Text:
*
* By default, and when _text/plain_ is accepted a simple stack trace
* or error message will be returned.
*
* JSON:
*
* When _application/json_ is accepted, connect will respond with
* an object in the form of `{ "success": false, "errors": errors }`.
*
* HTML:
*
* When accepted connect will output a nice html stack trace.
*
* @param {Object} options
* @return {Function}
* @api public
*/
var _ = require('underscore');
exports = module.exports = function errorHandler(options){
options = options || {};
// defaults
var showStack = options.showStack || options.stack
, showMessage = options.showMessage || options.message
, dumpExceptions = options.dumpExceptions || options.dump
, formatUrl = options.formatUrl;
return function errorHandler(err, req, res, next){
if (_.isArray(err)) {
err = _.first(err);
_.each(err, function(elem){
err.message += ', ' + elem.message;
});
}
err.status ? res.statusCode = err.status : res.statusCode = 500;
if (dumpExceptions) console.error(err.stack);
var stack = [];
if (showStack) {
stack = (err.stack || '').split('\n').slice(1);
}
var accept = req.headers.accept || '';
// html
if (~accept.indexOf('html')) {
res.locals({
stack: stack,
title: exports.title,
statusCode: res.statusCode,
errors: exports.escape(err.toString())
});
res.setHeader('Content-Type', 'text/html');
res.render('error', {layout: false});
// json
} else if (~accept.indexOf('json')) {
var json = JSON.stringify({ success: false, errors: err.message });
res.setHeader('Content-Type', 'application/json');
res.end(json);
// plain text
} else {
res.writeHead(res.statusCode, { 'Content-Type': 'text/plain' });
res.end(err.stack);
}
};
};
exports.escape = function(html){
return String(html)
.replace(/&(?!\w+;)/g, '&')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;');
};
/**
* Template title.
*/
exports.title = 'App Error';
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment