100 lines · 2.8 KB · JavaScript
RawDownload
/*! * 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';