2019-05-09 12:51:57 +00:00
|
|
|
// Copyright IBM Corp. 2016,2018. All Rights Reserved.
|
2016-05-11 11:53:28 +00:00
|
|
|
// Node module: strong-error-handler
|
|
|
|
// This file is licensed under the MIT License.
|
|
|
|
// License text available at https://opensource.org/licenses/MIT
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
2016-08-17 20:51:32 +00:00
|
|
|
var path = require('path');
|
|
|
|
var SG = require('strong-globalize');
|
|
|
|
SG.SetRootDir(path.resolve(__dirname, '..'));
|
2016-05-11 11:53:28 +00:00
|
|
|
var buildResponseData = require('./data-builder');
|
|
|
|
var debug = require('debug')('strong-error-handler');
|
|
|
|
var format = require('util').format;
|
|
|
|
var logToConsole = require('./logger');
|
2016-05-27 15:04:20 +00:00
|
|
|
var negotiateContentProducer = require('./content-negotiation');
|
2016-05-11 11:53:28 +00:00
|
|
|
|
|
|
|
function noop() {
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a middleware error handler function.
|
|
|
|
*
|
|
|
|
* @param {Object} options
|
|
|
|
* @returns {Function}
|
|
|
|
*/
|
2018-08-08 17:28:45 +00:00
|
|
|
function createStrongErrorHandler(options) {
|
2016-05-11 11:53:28 +00:00
|
|
|
options = options || {};
|
|
|
|
|
|
|
|
debug('Initializing with options %j', options);
|
|
|
|
|
|
|
|
// Log all errors via console.error (enabled by default)
|
|
|
|
var logError = options.log !== false ? logToConsole : noop;
|
|
|
|
|
|
|
|
return function strongErrorHandler(err, req, res, next) {
|
|
|
|
logError(req, err);
|
2018-08-08 17:28:45 +00:00
|
|
|
writeErrorToResponse(err, req, res, options);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Writes thrown error to response
|
|
|
|
*
|
|
|
|
* @param {Error} err
|
|
|
|
* @param {Express.Request} req
|
|
|
|
* @param {Express.Response} res
|
|
|
|
* @param {Object} options
|
|
|
|
*/
|
|
|
|
function writeErrorToResponse(err, req, res, options) {
|
|
|
|
debug('Handling %s', err.stack || err);
|
|
|
|
|
|
|
|
options = options || {};
|
2016-05-11 11:53:28 +00:00
|
|
|
|
2018-08-08 17:28:45 +00:00
|
|
|
if (res._header) {
|
|
|
|
debug('Response was already sent, closing the underlying connection');
|
|
|
|
return req.socket.destroy();
|
|
|
|
}
|
2016-05-11 11:53:28 +00:00
|
|
|
|
2018-08-08 17:28:45 +00:00
|
|
|
// this will alter the err object, to handle when res.statusCode is an error
|
|
|
|
if (!err.status && !err.statusCode && res.statusCode >= 400)
|
|
|
|
err.statusCode = res.statusCode;
|
2016-05-13 15:27:53 +00:00
|
|
|
|
2018-08-08 17:28:45 +00:00
|
|
|
var data = buildResponseData(err, options);
|
|
|
|
debug('Response status %s data %j', data.statusCode, data);
|
2016-05-11 11:53:28 +00:00
|
|
|
|
2018-08-08 17:28:45 +00:00
|
|
|
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
|
|
res.statusCode = data.statusCode;
|
2016-05-11 11:53:28 +00:00
|
|
|
|
2018-08-08 17:28:45 +00:00
|
|
|
var sendResponse = negotiateContentProducer(req, warn, options);
|
|
|
|
sendResponse(res, data);
|
2017-01-31 09:02:17 +00:00
|
|
|
|
2018-08-08 17:28:45 +00:00
|
|
|
function warn(msg) {
|
|
|
|
res.header('X-Warning', msg);
|
|
|
|
debug(msg);
|
|
|
|
}
|
2016-05-11 11:53:28 +00:00
|
|
|
};
|
2018-08-08 17:28:45 +00:00
|
|
|
|
|
|
|
exports = module.exports = createStrongErrorHandler;
|
|
|
|
exports.writeErrorToResponse = writeErrorToResponse;
|