100 lines
2.8 KiB
JavaScript
100 lines
2.8 KiB
JavaScript
|
/*!
|
||
|
* Connect - errorHandler
|
||
|
* Copyright(c) 2010 Sencha Inc.
|
||
|
* Copyright(c) 2011 TJ Holowaychuk
|
||
|
* MIT Licensed
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Module dependencies.
|
||
|
*/
|
||
|
|
||
|
var utils = require('../utils')
|
||
|
, url = require('url')
|
||
|
, fs = require('fs');
|
||
|
|
||
|
/**
|
||
|
* 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 `{ "error": error }`.
|
||
|
*
|
||
|
* HTML:
|
||
|
*
|
||
|
* When accepted connect will output a nice html stack trace.
|
||
|
*
|
||
|
* @param {Object} options
|
||
|
* @return {Function}
|
||
|
* @api public
|
||
|
*/
|
||
|
|
||
|
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){
|
||
|
res.statusCode = 500;
|
||
|
if (dumpExceptions) console.error(err.stack);
|
||
|
if (showStack) {
|
||
|
var accept = req.headers.accept || '';
|
||
|
// html
|
||
|
if (~accept.indexOf('html')) {
|
||
|
fs.readFile(__dirname + '/../public/style.css', 'utf8', function(e, style){
|
||
|
fs.readFile(__dirname + '/../public/error.html', 'utf8', function(e, html){
|
||
|
var stack = (err.stack || '')
|
||
|
.split('\n').slice(1)
|
||
|
.map(function(v){ return '<li>' + v + '</li>'; }).join('');
|
||
|
html = html
|
||
|
.replace('{style}', style)
|
||
|
.replace('{stack}', stack)
|
||
|
.replace('{title}', exports.title)
|
||
|
.replace(/\{error\}/g, utils.escape(err.toString()));
|
||
|
res.setHeader('Content-Type', 'text/html');
|
||
|
res.end(html);
|
||
|
});
|
||
|
});
|
||
|
// json
|
||
|
} else if (~accept.indexOf('json')) {
|
||
|
var json = JSON.stringify({ error: err });
|
||
|
res.setHeader('Content-Type', 'application/json');
|
||
|
res.end(json);
|
||
|
// plain text
|
||
|
} else {
|
||
|
res.writeHead(500, { 'Content-Type': 'text/plain' });
|
||
|
res.end(err.stack);
|
||
|
}
|
||
|
} else {
|
||
|
var body = showMessage
|
||
|
? err.toString()
|
||
|
: 'Internal Server Error';
|
||
|
res.setHeader('Content-Type', 'text/plain');
|
||
|
res.end(body);
|
||
|
}
|
||
|
};
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Template title.
|
||
|
*/
|
||
|
|
||
|
exports.title = 'Connect';
|