From 61b1f47b02275a322df9d38c75b748e19f7361ef Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Thu, 1 Jan 2015 12:44:16 -0500 Subject: [PATCH] Fix heading content to not include stack fixes #10 --- HISTORY.md | 5 +++++ index.js | 43 ++++++++++++++++++++++++++++++++----------- test/test.js | 6 +++--- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 7c3918a..4e55397 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,3 +1,8 @@ +unreleased +========== + + * Fix heading content to not include stack + 1.2.3 / 2014-11-21 ================== diff --git a/index.js b/index.js index e4ea469..5d20e57 100644 --- a/index.js +++ b/index.js @@ -19,7 +19,9 @@ var util = require('util') * Module variables. */ +var doubleSpaceGlobalRegExp = / /g var inspect = util.inspect +var newLineGlobalRegExp = /\n/g var toString = Object.prototype.toString /** @@ -85,17 +87,25 @@ exports = module.exports = function errorHandler(){ if (e) return next(e); fs.readFile(__dirname + '/public/error.html', 'utf8', function(e, html){ if (e) return next(e); - var stack = String(err.stack || '') - .split('\n').slice(1) - .map(function(v){ return '
  • ' + escapeHtml(v).replace(/ /g, '  ') + '
  • '; }).join(''); - html = html - .replace('{style}', style) - .replace('{stack}', stack) - .replace('{title}', escapeHtml(exports.title)) - .replace('{statusCode}', res.statusCode) - .replace(/\{error\}/g, escapeHtml(stringify(err)).replace(/ /g, '  ').replace(/\n/g, '
    ')); - res.setHeader('Content-Type', 'text/html; charset=utf-8'); - res.end(html); + var str = stringify(err) + var isInspect = !err.stack && String(err) === toString.call(err) + var errorHtml = !isInspect + ? escapeHtmlBlock(str.split('\n', 1)[0] || 'Error') + : 'Error' + var stack = !isInspect + ? String(str).split('\n').slice(1) + : [str] + var stackHtml = stack + .map(function (v) { return '
  • ' + escapeHtmlBlock(v) + '
  • ' }) + .join('') + var body = html + .replace('{style}', style) + .replace('{stack}', stackHtml) + .replace('{title}', escapeHtml(exports.title)) + .replace('{statusCode}', res.statusCode) + .replace(/\{error\}/g, errorHtml) + res.setHeader('Content-Type', 'text/html; charset=utf-8') + res.end(body) }); }); // json @@ -119,6 +129,17 @@ exports = module.exports = function errorHandler(){ exports.title = 'Connect'; +/** + * Escape a block of HTML, preserving whitespace. + * @api private + */ + +function escapeHtmlBlock(str) { + return escapeHtml(str) + .replace(doubleSpaceGlobalRegExp, '  ') + .replace(newLineGlobalRegExp, '
    ') +} + /** * Stringify a value. * @api private diff --git a/test/test.js b/test/test.js index 5410e33..5f348ab 100644 --- a/test/test.js +++ b/test/test.js @@ -58,9 +58,9 @@ describe('errorHandler()', function () { .get('/') .set('Accept', 'text/html') .expect('Content-Type', /text\/html/) - .expect(//) - .expect(/Error: boom!/) - .expect(/    at/) + .expect(/<title>Error: boom!<\/title>/) + .expect(/<h2><em>500<\/em> Error: boom!<\/h2>/) + .expect(/<li>    at/) .end(done) });