diff --git a/index.js b/index.js index a8927da..3a6cfdf 100644 --- a/index.js +++ b/index.js @@ -292,6 +292,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) } @@ -347,7 +352,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 60a737f..a3c0b38 100644 --- a/lib/layer.js +++ b/lib/layer.js @@ -28,23 +28,34 @@ 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 pathObj = { + path: path, + keys: [] + } + pathObj.regexp = pathRegexp(path, pathObj.keys, opts) + + return pathObj + }) } /** @@ -107,24 +118,33 @@ 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) { @@ -142,7 +162,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 ea3d73c..448b923 100644 --- a/test/router.js +++ b/test/router.js @@ -1129,6 +1129,31 @@ describe('Router', function () { .expect(200, 'saw GET /bar', done) }) }) + + describe('req.matchedRoutes', function () { + it('should store matchedRoutes in request', function (done) { + var router = new Router() + var barRouter = new Router() + var bazRouter = new Router() + var server = createServer(router) + var matchedRoutes + + router.use(['/foo/:id', '/foe'], barRouter) + barRouter.use(['/bar'], bazRouter) + bazRouter.get(['/bez', '/baz/:subId'], function (req, res, next) { + matchedRoutes = req.matchedRoutes + next() + }) + router.use(saw) + + request(server) + .get('/foo/10/bar/baz/30') + .expect(200, 'saw GET /foo/10/bar/baz/30', function (err, res) { + assert.deepEqual(matchedRoutes, ['/foo/:id', '/bar', '/baz/:subId']) + done(err) + }) + }) + }) }) function helloWorld(req, res) {