Skip to content

Commit

Permalink
Store matched routes in request
Browse files Browse the repository at this point in the history
  • Loading branch information
ajfranzoia authored and gabegorelick committed Jan 3, 2020
1 parent dbaa56e commit c3df1fb
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 11 deletions.
7 changes: 6 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -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) {
Expand Down
42 changes: 32 additions & 10 deletions lib/layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 || '<anonymous>'
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
})
}

/**
Expand Down Expand Up @@ -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
}

Expand All @@ -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])

Expand Down
132 changes: 132 additions & 0 deletions test/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit c3df1fb

Please sign in to comment.