Skip to content

Commit

Permalink
Fix: remove invalid triggering of uncaughtException handler (#1710)
Browse files Browse the repository at this point in the history
The previous (prior to 7.x) functionality for uncaught exceptions only triggered the `uncaughtException` handler if it was truly an uncaught thrown error. Right now in Restify 7, if you turn on `handleUncaughtExceptions` and add a listener for the event, all errors from `next(err)` and internal errors like `MethodNotAllowed` will trigger the `uncaughtException` handler.
  • Loading branch information
mridgway authored and DonutEspresso committed Oct 30, 2018
1 parent 4111e1e commit ee69806
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 5 deletions.
22 changes: 17 additions & 5 deletions lib/server.js
Expand Up @@ -816,7 +816,7 @@ Server.prototype._onRequest = function _onRequest(req, res) {
handlerDomain.add(req);
handlerDomain.add(res);
handlerDomain.on('error', function onError(err) {
self._onHandlerError(err, req, res);
self._onHandlerError(err, req, res, true);
});
handlerDomain.run(function run() {
self._runPre(req, res);
Expand Down Expand Up @@ -1065,9 +1065,15 @@ Server.prototype._onHandlerStop = function _onHandlerStop(req, res) {
* @param {Error|String|undefined} err - router handler error or route name
* @param {Request} req - request
* @param {Response} res - response
* @param {boolean} isUncaught - whether the error is uncaught
* @returns {undefined} no return value
*/
Server.prototype._onHandlerError = function _onHandlerError(err, req, res) {
Server.prototype._onHandlerError = function _onHandlerError(
err,
req,
res,
isUncaught
) {
var self = this;

// Call route by name
Expand Down Expand Up @@ -1098,7 +1104,7 @@ Server.prototype._onHandlerError = function _onHandlerError(err, req, res) {
res.err = res.err || err;

// Error happened in router handlers
self._routeErrorResponse(req, res, err);
self._routeErrorResponse(req, res, err, isUncaught);
};

/**
Expand Down Expand Up @@ -1256,16 +1262,22 @@ Server.prototype._finishReqResCycle = function _finishReqResCycle(
* @param {Request} req - the request object
* @param {Response} res - the response object
* @param {Error} err - error
* @param {boolean} isUncaught - whether the error is uncaught
* @returns {undefined} no return value
*/
Server.prototype._routeErrorResponse = function _routeErrorResponse(
req,
res,
err
err,
isUncaught
) {
var self = this;

if (self.listenerCount('uncaughtException') > 1) {
if (
isUncaught &&
self.handleUncaughtExceptions &&
self.listenerCount('uncaughtException') > 1
) {
self.emit('uncaughtException', req, res, req.route, err);
return;
}
Expand Down
38 changes: 38 additions & 0 deletions test/server.test.js
Expand Up @@ -674,6 +674,44 @@ test('GH-77 uncaughtException (default behavior)', function(t) {
});
});

// eslint-disable-next-line
test('handleUncaughtExceptions should not call handler for internal errors', function(t) {
SERVER.get('/', function(req, res, next) {
// This route is not used for the test but at least one route needs to
// be registered to Restify in order for routing logic to be run
assert.fail('should not run');
});

SERVER.on('uncaughtException', function throwError(err) {
t.ifError(err);
t.end();
});

CLIENT.head('/', function(err, _, res) {
t.ok(err);
t.equal(res.statusCode, 405);
t.end();
});
});

// eslint-disable-next-line
test('handleUncaughtExceptions should not call handler for next(new Error())', function(t) {
SERVER.get('/', function(req, res, next) {
next(new Error('I am not fatal'));
});

SERVER.on('uncaughtException', function throwError(err) {
t.ifError(err);
t.end();
});

CLIENT.get('/', function(err, _, res) {
t.ok(err);
t.equal(res.statusCode, 500);
t.end();
});
});

test('GH-77 uncaughtException (with custom handler)', function(t) {
SERVER.on('uncaughtException', function(req, res, route, err) {
res.send(204);
Expand Down

0 comments on commit ee69806

Please sign in to comment.