@@ -19,7 +19,9 @@ var util = require('util')
1919 * Module variables.
2020 */
2121
22+ var doubleSpaceGlobalRegExp = / / g
2223var inspect = util . inspect
24+ var newLineGlobalRegExp = / \n / g
2325var toString = Object . prototype . toString
2426
2527/**
@@ -85,17 +87,25 @@ exports = module.exports = function errorHandler(){
8587 if ( e ) return next ( e ) ;
8688 fs . readFile ( __dirname + '/public/error.html' , 'utf8' , function ( e , html ) {
8789 if ( e ) return next ( e ) ;
88- var stack = String ( err . stack || '' )
89- . split ( '\n' ) . slice ( 1 )
90- . map ( function ( v ) { return '<li>' + escapeHtml ( v ) . replace ( / / g, ' ' ) + '</li>' ; } ) . join ( '' ) ;
91- html = html
92- . replace ( '{style}' , style )
93- . replace ( '{stack}' , stack )
94- . replace ( '{title}' , escapeHtml ( exports . title ) )
95- . replace ( '{statusCode}' , res . statusCode )
96- . replace ( / \{ e r r o r \} / g, escapeHtml ( stringify ( err ) ) . replace ( / / g, ' ' ) . replace ( / \n / g, '<br>' ) ) ;
97- res . setHeader ( 'Content-Type' , 'text/html; charset=utf-8' ) ;
98- res . end ( html ) ;
90+ var str = stringify ( err )
91+ var isInspect = ! err . stack && String ( err ) === toString . call ( err )
92+ var errorHtml = ! isInspect
93+ ? escapeHtmlBlock ( str . split ( '\n' , 1 ) [ 0 ] || 'Error' )
94+ : 'Error'
95+ var stack = ! isInspect
96+ ? String ( str ) . split ( '\n' ) . slice ( 1 )
97+ : [ str ]
98+ var stackHtml = stack
99+ . map ( function ( v ) { return '<li>' + escapeHtmlBlock ( v ) + '</li>' } )
100+ . join ( '' )
101+ var body = html
102+ . replace ( '{style}' , style )
103+ . replace ( '{stack}' , stackHtml )
104+ . replace ( '{title}' , escapeHtml ( exports . title ) )
105+ . replace ( '{statusCode}' , res . statusCode )
106+ . replace ( / \{ e r r o r \} / g, errorHtml )
107+ res . setHeader ( 'Content-Type' , 'text/html; charset=utf-8' )
108+ res . end ( body )
99109 } ) ;
100110 } ) ;
101111 // json
@@ -119,6 +129,17 @@ exports = module.exports = function errorHandler(){
119129
120130exports . title = 'Connect' ;
121131
132+ /**
133+ * Escape a block of HTML, preserving whitespace.
134+ * @api private
135+ */
136+
137+ function escapeHtmlBlock ( str ) {
138+ return escapeHtml ( str )
139+ . replace ( doubleSpaceGlobalRegExp , ' ' )
140+ . replace ( newLineGlobalRegExp , '<br>' )
141+ }
142+
122143/**
123144 * Stringify a value.
124145 * @api private
0 commit comments