From 79fb5395ab26c2f09f661b05c0e7222f3d0d4c37 Mon Sep 17 00:00:00 2001 From: Buddy Sandidge Date: Mon, 8 Feb 2016 00:10:25 -0800 Subject: [PATCH] Correctly handle not found errors in partial routes Take care of obvious case. A router with a route to '/foo/bar' but not for '/foo', should give a not found error. --- lib/error.js | 14 ++++++++++++++ lib/route-node.js | 5 +++-- lib/router.js | 10 ++++++++-- test/router.js | 10 ++++++++++ 4 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 lib/error.js diff --git a/lib/error.js b/lib/error.js new file mode 100644 index 0000000..765cf74 --- /dev/null +++ b/lib/error.js @@ -0,0 +1,14 @@ +var util = require('util') + +function NotFound(message, options) { + Error.call(this) + options = options || {} + this.message = message || '' + this.location = options.location || '' +} + +util.inherits(NotFound, Error) + +module.exports = { + NotFound: NotFound +} diff --git a/lib/route-node.js b/lib/route-node.js index 957685e..2fc4cae 100644 --- a/lib/route-node.js +++ b/lib/route-node.js @@ -1,4 +1,5 @@ 'use strict' +var NotFoundError = require('./error').NotFound var utils = require('./utils') var assign = utils.assign @@ -10,8 +11,8 @@ var noop = utils.noop function RouteNode (options) { options = options || {} this._children = Object.create(null) - this._regExs = Object.create(null) this._funcs = Object.create(null) + this._regExs = Object.create(null) } assign(RouteNode.prototype, { @@ -71,7 +72,7 @@ assign(RouteNode.prototype, { return results.node.get(parts, args.concat(results.args), done) } - return done(new Error('not found')) + return done(new NotFoundError('not found', {location: parts})) }, _getRegexChild: function _getRegexChild(part) { diff --git a/lib/router.js b/lib/router.js index e186ab5..69135e9 100644 --- a/lib/router.js +++ b/lib/router.js @@ -1,10 +1,12 @@ 'use strict' var url = require('url') +var NotFoundError = require('./error').NotFound var RouteNode = require('./route-node') var utils = require('./utils') var assign = utils.assign var isArray = utils.isArray +var isFunction = utils.isFunction var isString = utils.isString var noop = utils.noop @@ -25,7 +27,11 @@ assign(Router.prototype, { if (err) { return done(err) } else { - return done(null, func.apply(context, args)) + if (isFunction(func)) { + return done(null, func.apply(context, args)) + } else { + return done(new NotFoundError('not found', {location: path})) + } } }) }, @@ -53,7 +59,7 @@ assign(Router.prototype, { }) Router.isNotFound = function isNotFound(err) { - return err instanceof Error && /not found/.exec(err.message) !== null + return err instanceof NotFoundError } module.exports = Router diff --git a/test/router.js b/test/router.js index 8baab72..62466b0 100644 --- a/test/router.js +++ b/test/router.js @@ -1,5 +1,6 @@ var expect = require('expect') var Router = require('../lib/router') +var NotFoundError = require('../lib/error').NotFound describe('Router', function () { it('→ exists', function () { @@ -26,6 +27,15 @@ describe('Router', function () { }) }) + it('→ partial route is a not found error', function (done) { + var router = new Router() + router.add(['/user', /^(\d+)$/], function (number) { return number }) + router.route('/user/', function (err) { + expect(err).toBeA(NotFoundError) + done() + }) + }) + it('→ get error in callback for missing handler', function (done) { var router = new Router() router.route('/some/fake/path', function (err, handlerResult) {