33 * Copyright(c) 2010 Sencha Inc.
44 * Copyright(c) 2011 TJ Holowaychuk
55 * Copyright(c) 2014 Jonathan Ong
6- * Copyright(c) 2014 Douglas Christopher Wilson
6+ * Copyright(c) 2014-2015 Douglas Christopher Wilson
77 * MIT Licensed
88 */
99
@@ -22,7 +22,9 @@ var util = require('util')
2222 * @private
2323 */
2424
25+ var doubleSpaceGlobalRegExp = / / g
2526var inspect = util . inspect
27+ var newLineGlobalRegExp = / \n / g
2628var toString = Object . prototype . toString
2729
2830/* istanbul ignore next */
@@ -111,17 +113,24 @@ exports = module.exports = function errorHandler(options) {
111113 if ( e ) return next ( e ) ;
112114 fs . readFile ( __dirname + '/public/error.html' , 'utf8' , function ( e , html ) {
113115 if ( e ) return next ( e ) ;
114- var stack = String ( err . stack || '' )
115- . split ( '\n' ) . slice ( 1 )
116- . map ( function ( v ) { return '<li>' + escapeHtml ( v ) . replace ( / / g, ' ' ) + '</li>' ; } ) . join ( '' ) ;
117- html = html
118- . replace ( '{style}' , style )
119- . replace ( '{stack}' , stack )
120- . replace ( '{title}' , escapeHtml ( exports . title ) )
121- . replace ( '{statusCode}' , res . statusCode )
122- . replace ( / \{ e r r o r \} / g, escapeHtml ( str ) . replace ( / / g, ' ' ) . replace ( / \n / g, '<br>' ) )
123- res . setHeader ( 'Content-Type' , 'text/html; charset=utf-8' ) ;
124- res . end ( html ) ;
116+ var isInspect = ! err . stack && String ( err ) === toString . call ( err )
117+ var errorHtml = ! isInspect
118+ ? escapeHtmlBlock ( str . split ( '\n' , 1 ) [ 0 ] || 'Error' )
119+ : 'Error'
120+ var stack = ! isInspect
121+ ? String ( str ) . split ( '\n' ) . slice ( 1 )
122+ : [ str ]
123+ var stackHtml = stack
124+ . map ( function ( v ) { return '<li>' + escapeHtmlBlock ( v ) + '</li>' } )
125+ . join ( '' )
126+ var body = html
127+ . replace ( '{style}' , style )
128+ . replace ( '{stack}' , stackHtml )
129+ . replace ( '{title}' , escapeHtml ( exports . title ) )
130+ . replace ( '{statusCode}' , res . statusCode )
131+ . replace ( / \{ e r r o r \} / g, errorHtml )
132+ res . setHeader ( 'Content-Type' , 'text/html; charset=utf-8' )
133+ res . end ( body )
125134 } ) ;
126135 } ) ;
127136 // json
@@ -145,6 +154,17 @@ exports = module.exports = function errorHandler(options) {
145154
146155exports . title = 'Connect' ;
147156
157+ /**
158+ * Escape a block of HTML, preserving whitespace.
159+ * @api private
160+ */
161+
162+ function escapeHtmlBlock ( str ) {
163+ return escapeHtml ( str )
164+ . replace ( doubleSpaceGlobalRegExp , ' ' )
165+ . replace ( newLineGlobalRegExp , '<br>' )
166+ }
167+
148168/**
149169 * Stringify a value.
150170 * @api private
0 commit comments