From c3df1fb94484d88734f11ea99ae3d2518548ce8e Mon Sep 17 00:00:00 2001 From: Augusto Franzoia Date: Sat, 13 Feb 2016 17:10:07 -0300 Subject: [PATCH] Store matched routes in request --- index.js | 7 ++- lib/layer.js | 42 ++++++++++++---- test/router.js | 132 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+), 11 deletions(-) diff --git a/index.js b/index.js index 7c68516..0f5f80f 100644 --- a/index.js +++ b/index.js @@ -287,6 +287,11 @@ Router.prototype.handle = function handle(req, res, callback) { return next(layerError || err) } + if (layer.path) { + req.matchedRoutes = req.matchedRoutes || [] + req.matchedRoutes.push(layer.matchedPath.path) + } + if (route) { return layer.handle_request(req, res, next) } @@ -342,7 +347,7 @@ Router.prototype.process_params = function process_params(layer, called, req, re var params = this.params // captured parameters from the layer, keys and values - var keys = layer.keys + var keys = layer.matchedPath && layer.matchedPath.keys // fast track if (!keys || keys.length === 0) { diff --git a/lib/layer.js b/lib/layer.js index c012165..8011f41 100644 --- a/lib/layer.js +++ b/lib/layer.js @@ -28,23 +28,35 @@ var hasOwnProperty = Object.prototype.hasOwnProperty module.exports = Layer -function Layer(path, options, fn) { +function Layer(paths, options, fn) { if (!(this instanceof Layer)) { - return new Layer(path, options, fn) + return new Layer(paths, options, fn) } - debug('new %o', path) + debug('new %o', paths) var opts = options || {} this.handle = fn this.name = fn.name || '' this.params = undefined this.path = undefined - this.regexp = pathRegexp(path, this.keys = [], opts) + this.matchedPath = undefined // set fast path flags - this.regexp.fast_star = path === '*' - this.regexp.fast_slash = path === '/' && opts.end === false + this.fastStar = paths === '*' + this.fastSlash = paths === '/' && opts.end === false + + this.paths = !Array.isArray(paths) ? [paths] : paths + this.paths = this.paths.map(function (path) { + var keys = [] + var pathObj = { + path: path, + keys: keys, + regexp: pathRegexp(path, keys, opts) + } + + return pathObj + }) } /** @@ -123,29 +135,39 @@ Layer.prototype.handle_request = function handle(req, res, next) { Layer.prototype.match = function match(path) { var match + var checkPath if (path != null) { // fast path non-ending match for / (any path matches) - if (this.regexp.fast_slash) { + if (this.fastSlash) { this.params = {} this.path = '' + this.matchedPath = this.paths[0] return true } // fast path for * (everything matched in a param) - if (this.regexp.fast_star) { + if (this.fastStar) { this.params = {'0': decode_param(path)} this.path = path + this.matchedPath = this.paths[0] return true } // match the path - match = this.regexp.exec(path) + for (var i = 0; i < this.paths.length; i++) { + checkPath = this.paths[i] + if (match = checkPath.regexp.exec(path)) { + this.matchedPath = checkPath + break + } + } } if (!match) { this.params = undefined this.path = undefined + this.matchedPath = undefined return false } @@ -158,7 +180,7 @@ Layer.prototype.match = function match(path) { var params = this.params for (var i = 1; i < match.length; i++) { - var key = keys[i - 1] + var key = this.matchedPath.keys[i - 1] var prop = key.name var val = decode_param(match[i]) diff --git a/test/router.js b/test/router.js index 0bb89a4..7158dd7 100644 --- a/test/router.js +++ b/test/router.js @@ -1243,6 +1243,138 @@ describe('Router', function () { .expect(200, 'saw GET /bar', done) }) }) + + describe('req.matchedRoutes', function () { + it('should be set if there is a match', function (done) { + var router = new Router() + var server = createServer(router) + var matchedRoutes + + router.get('/foo', function (req, res, next) { + matchedRoutes = req.matchedRoutes + next() + }) + router.use(saw) + + request(server) + .get('/foo') + .expect(200, 'saw GET /foo', function (err, res) { + assert.deepEqual(matchedRoutes, ['/foo']) + done(err) + }) + }) + + it('should be undefined if there is not a match', function (done) { + var router = new Router() + var server = createServer(router) + var matchedRoutes + + router.use(function (req, res, next) { + matchedRoutes = req.matchedRoutes + next() + }) + + request(server) + .get('/foo') + .expect(404, function (err, res) { + assert.strictEqual(matchedRoutes, undefined) + done(err) + }) + }) + + it('should work with sub-routers', function (done) { + var router = new Router() + var fooRouter = new Router() + var server = createServer(router) + var matchedRoutes + + router.use('/foo', fooRouter) + fooRouter.get('/bar', function (req, res, next) { + matchedRoutes = req.matchedRoutes + next() + }) + router.use(saw) + + request(server) + .get('/foo/bar') + .expect(200, 'saw GET /foo/bar', function (err, res) { + assert.deepEqual(matchedRoutes, ['/foo', '/bar']) + done(err) + }) + }) + + it('should be undefined if sub-router did not match', function (done) { + var router = new Router() + var fooRouter = new Router() + var server = createServer(router) + var matchedRoutes + + router.use('/foo', fooRouter) + fooRouter.get('/bar', function (req, res, next) { + matchedRoutes = req.matchedRoutes + next() + }) + router.use(saw) + + request(server) + .get('/foo/baz') + .expect(200, 'saw GET /foo/baz', function (err, res) { + assert.strictEqual(matchedRoutes, undefined) + done(err) + }) + }) + + it('should work with regexp-defined routes', function (done) { + var router = new Router() + var server = createServer(router) + var matchedRoutes + var regexp = /fo+/ + + router.get(regexp, function (req, res, next) { + matchedRoutes = req.matchedRoutes + next() + }) + router.use(saw) + + request(server) + .get('/foo') + .expect(200, 'saw GET /foo', function (err, res) { + assert.deepEqual(matchedRoutes, [regexp]) + done(err) + }) + }) + + it('should support routes defined with arrays of paths', function (done) { + var router = new Router() + var server = createServer(router) + var matchedRoutes + + router.get(['/foo', '/bar/:id'], function (req, res, next) { + matchedRoutes = req.matchedRoutes + next() + }) + router.use(saw) + + request(server) + .get('/foo') + .expect(200, 'saw GET /foo', function (err, res) { + if (err) { + return done(err) + } + assert.deepEqual(matchedRoutes, ['/foo']) + + request(server) + .get('/bar/1') + .expect(200, 'saw GET /bar/1', function (err, res) { + if (err) { + return done(err) + } + assert.deepEqual(matchedRoutes, ['/bar/:id']) + done() + }) + }) + }) + }) }) function helloWorld(req, res) {