Roughing out the demo app
This commit is contained in:
198
node_modules/errorhandler/index.js
generated
vendored
Normal file
198
node_modules/errorhandler/index.js
generated
vendored
Normal file
@@ -0,0 +1,198 @@
|
||||
/*!
|
||||
* errorhandler
|
||||
* Copyright(c) 2010 Sencha Inc.
|
||||
* Copyright(c) 2011 TJ Holowaychuk
|
||||
* Copyright(c) 2014 Jonathan Ong
|
||||
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
* @private
|
||||
*/
|
||||
|
||||
var accepts = require('accepts')
|
||||
var escapeHtml = require('escape-html')
|
||||
var fs = require('fs')
|
||||
var path = require('path')
|
||||
var util = require('util')
|
||||
|
||||
/**
|
||||
* Module variables.
|
||||
* @private
|
||||
*/
|
||||
|
||||
var DOUBLE_SPACE_REGEXP = /\x20{2}/g
|
||||
var NEW_LINE_REGEXP = /\n/g
|
||||
var STYLESHEET = fs.readFileSync(path.join(__dirname, '/public/style.css'), 'utf8')
|
||||
var TEMPLATE = fs.readFileSync(path.join(__dirname, '/public/error.html'), 'utf8')
|
||||
var inspect = util.inspect
|
||||
var toString = Object.prototype.toString
|
||||
|
||||
/* istanbul ignore next */
|
||||
var defer = typeof setImmediate === 'function'
|
||||
? setImmediate
|
||||
: function (fn) { process.nextTick(fn.bind.apply(fn, arguments)) }
|
||||
|
||||
/**
|
||||
* 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 (options) {
|
||||
// get environment
|
||||
var env = process.env.NODE_ENV || 'development'
|
||||
|
||||
// get options
|
||||
var opts = options || {}
|
||||
|
||||
// get log option
|
||||
var log = opts.log === undefined
|
||||
? env !== 'test'
|
||||
: opts.log
|
||||
|
||||
if (typeof log !== 'function' && typeof log !== 'boolean') {
|
||||
throw new TypeError('option log must be function or boolean')
|
||||
}
|
||||
|
||||
// default logging using console.error
|
||||
if (log === true) {
|
||||
log = logerror
|
||||
}
|
||||
|
||||
return function errorHandler (err, req, res, next) {
|
||||
// respect err.statusCode
|
||||
if (err.statusCode) {
|
||||
res.statusCode = err.statusCode
|
||||
}
|
||||
|
||||
// respect err.status
|
||||
if (err.status) {
|
||||
res.statusCode = err.status
|
||||
}
|
||||
|
||||
// default status code to 500
|
||||
if (res.statusCode < 400) {
|
||||
res.statusCode = 500
|
||||
}
|
||||
|
||||
// log the error
|
||||
var str = stringify(err)
|
||||
if (log) {
|
||||
defer(log, err, str, req, res)
|
||||
}
|
||||
|
||||
// cannot actually respond
|
||||
if (res._header) {
|
||||
return req.socket.destroy()
|
||||
}
|
||||
|
||||
// negotiate
|
||||
var accept = accepts(req)
|
||||
var type = accept.type('html', 'json', 'text')
|
||||
|
||||
// Security header for content sniffing
|
||||
res.setHeader('X-Content-Type-Options', 'nosniff')
|
||||
|
||||
// html
|
||||
if (type === 'html') {
|
||||
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 '<li>' + escapeHtmlBlock(v) + '</li>' })
|
||||
.join('')
|
||||
var body = TEMPLATE
|
||||
.replace('{style}', STYLESHEET)
|
||||
.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
|
||||
} 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 }, null, 2)
|
||||
res.setHeader('Content-Type', 'application/json; charset=utf-8')
|
||||
res.end(json)
|
||||
// plain text
|
||||
} else {
|
||||
res.setHeader('Content-Type', 'text/plain; charset=utf-8')
|
||||
res.end(str)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Template title, framework authors may override this value.
|
||||
*/
|
||||
|
||||
exports.title = 'Connect'
|
||||
|
||||
/**
|
||||
* Escape a block of HTML, preserving whitespace.
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function escapeHtmlBlock (str) {
|
||||
return escapeHtml(str)
|
||||
.replace(DOUBLE_SPACE_REGEXP, ' ')
|
||||
.replace(NEW_LINE_REGEXP, '<br>')
|
||||
}
|
||||
|
||||
/**
|
||||
* Stringify a value.
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function stringify (val) {
|
||||
var stack = val.stack
|
||||
|
||||
if (stack) {
|
||||
return String(stack)
|
||||
}
|
||||
|
||||
var str = String(val)
|
||||
|
||||
return str === toString.call(val)
|
||||
? inspect(val)
|
||||
: str
|
||||
}
|
||||
|
||||
/**
|
||||
* Log error to console.
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function logerror (err, str) {
|
||||
console.error(str || err.stack)
|
||||
}
|
||||
Reference in New Issue
Block a user