Mercurial > hg > nodescore
view node_modules/errorhandler/index.js @ 84:a4a9059a3802
local to server
author | Rob Canning <rob@foo.net> |
---|---|
date | Mon, 28 Jul 2014 18:17:02 +0100 |
parents | 0c3a2942ddee |
children |
line wrap: on
line source
/*! * errorhandler * Copyright(c) 2010 Sencha Inc. * Copyright(c) 2011 TJ Holowaychuk * MIT Licensed */ /** * Module dependencies. */ var accepts = require('accepts') var escapeHtml = require('escape-html'); var fs = require('fs'); /** * Error handler: * * Development error handler, providing stack traces * and error message responses for requests accepting text, html, * or json. * * 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. * * @return {Function} * @api public */ exports = module.exports = function errorHandler(){ // get environment var env = process.env.NODE_ENV || 'development' return function errorHandler(err, req, res, next){ // respect err.status if (err.status) { res.statusCode = err.status } // default status code to 500 if (res.statusCode < 400) { res.statusCode = 500 } // write error to console if (env !== 'test') { console.error(err.stack || String(err)) } // cannot actually respond if (res._header) { return req.socket.destroy() } // negotiate var accept = accepts(req) var type = accept.types('html', 'json', 'text') // Security header for content sniffing res.setHeader('X-Content-Type-Options', 'nosniff') // html if (type === 'html') { fs.readFile(__dirname + '/public/style.css', 'utf8', function(e, style){ if (e) return next(e); fs.readFile(__dirname + '/public/error.html', 'utf8', function(e, html){ if (e) return next(e); var stack = (err.stack || '') .split('\n').slice(1) .map(function(v){ return '<li>' + escapeHtml(v).replace(/ /g, ' ') + '</li>'; }).join(''); html = html .replace('{style}', style) .replace('{stack}', stack) .replace('{title}', escapeHtml(exports.title)) .replace('{statusCode}', res.statusCode) .replace(/\{error\}/g, escapeHtml(String(err)).replace(/ /g, ' ').replace(/\n/g, '<br>')); res.setHeader('Content-Type', 'text/html; charset=utf-8'); res.end(html); }); }); // json } else if (type === 'json') { var error = { message: err.message, stack: err.stack }; for (var prop in err) error[prop] = err[prop]; var json = JSON.stringify({ error: error }); res.setHeader('Content-Type', 'application/json'); res.end(json); // plain text } else { res.setHeader('Content-Type', 'text/plain'); res.end(err.stack || String(err)); } }; }; /** * Template title, framework authors may override this value. */ exports.title = 'Connect';