Skip to content

Commit c3df1fb

Browse files
ajfranzoiagabegorelick
authored andcommitted
Store matched routes in request
1 parent dbaa56e commit c3df1fb

File tree

3 files changed

+170
-11
lines changed

3 files changed

+170
-11
lines changed

index.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,11 @@ Router.prototype.handle = function handle(req, res, callback) {
287287
return next(layerError || err)
288288
}
289289

290+
if (layer.path) {
291+
req.matchedRoutes = req.matchedRoutes || []
292+
req.matchedRoutes.push(layer.matchedPath.path)
293+
}
294+
290295
if (route) {
291296
return layer.handle_request(req, res, next)
292297
}
@@ -342,7 +347,7 @@ Router.prototype.process_params = function process_params(layer, called, req, re
342347
var params = this.params
343348

344349
// captured parameters from the layer, keys and values
345-
var keys = layer.keys
350+
var keys = layer.matchedPath && layer.matchedPath.keys
346351

347352
// fast track
348353
if (!keys || keys.length === 0) {

lib/layer.js

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,35 @@ var hasOwnProperty = Object.prototype.hasOwnProperty
2828

2929
module.exports = Layer
3030

31-
function Layer(path, options, fn) {
31+
function Layer(paths, options, fn) {
3232
if (!(this instanceof Layer)) {
33-
return new Layer(path, options, fn)
33+
return new Layer(paths, options, fn)
3434
}
3535

36-
debug('new %o', path)
36+
debug('new %o', paths)
3737
var opts = options || {}
3838

3939
this.handle = fn
4040
this.name = fn.name || '<anonymous>'
4141
this.params = undefined
4242
this.path = undefined
43-
this.regexp = pathRegexp(path, this.keys = [], opts)
43+
this.matchedPath = undefined
4444

4545
// set fast path flags
46-
this.regexp.fast_star = path === '*'
47-
this.regexp.fast_slash = path === '/' && opts.end === false
46+
this.fastStar = paths === '*'
47+
this.fastSlash = paths === '/' && opts.end === false
48+
49+
this.paths = !Array.isArray(paths) ? [paths] : paths
50+
this.paths = this.paths.map(function (path) {
51+
var keys = []
52+
var pathObj = {
53+
path: path,
54+
keys: keys,
55+
regexp: pathRegexp(path, keys, opts)
56+
}
57+
58+
return pathObj
59+
})
4860
}
4961

5062
/**
@@ -123,29 +135,39 @@ Layer.prototype.handle_request = function handle(req, res, next) {
123135

124136
Layer.prototype.match = function match(path) {
125137
var match
138+
var checkPath
126139

127140
if (path != null) {
128141
// fast path non-ending match for / (any path matches)
129-
if (this.regexp.fast_slash) {
142+
if (this.fastSlash) {
130143
this.params = {}
131144
this.path = ''
145+
this.matchedPath = this.paths[0]
132146
return true
133147
}
134148

135149
// fast path for * (everything matched in a param)
136-
if (this.regexp.fast_star) {
150+
if (this.fastStar) {
137151
this.params = {'0': decode_param(path)}
138152
this.path = path
153+
this.matchedPath = this.paths[0]
139154
return true
140155
}
141156

142157
// match the path
143-
match = this.regexp.exec(path)
158+
for (var i = 0; i < this.paths.length; i++) {
159+
checkPath = this.paths[i]
160+
if (match = checkPath.regexp.exec(path)) {
161+
this.matchedPath = checkPath
162+
break
163+
}
164+
}
144165
}
145166

146167
if (!match) {
147168
this.params = undefined
148169
this.path = undefined
170+
this.matchedPath = undefined
149171
return false
150172
}
151173

@@ -158,7 +180,7 @@ Layer.prototype.match = function match(path) {
158180
var params = this.params
159181

160182
for (var i = 1; i < match.length; i++) {
161-
var key = keys[i - 1]
183+
var key = this.matchedPath.keys[i - 1]
162184
var prop = key.name
163185
var val = decode_param(match[i])
164186

test/router.js

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,6 +1243,138 @@ describe('Router', function () {
12431243
.expect(200, 'saw GET /bar', done)
12441244
})
12451245
})
1246+
1247+
describe('req.matchedRoutes', function () {
1248+
it('should be set if there is a match', function (done) {
1249+
var router = new Router()
1250+
var server = createServer(router)
1251+
var matchedRoutes
1252+
1253+
router.get('/foo', function (req, res, next) {
1254+
matchedRoutes = req.matchedRoutes
1255+
next()
1256+
})
1257+
router.use(saw)
1258+
1259+
request(server)
1260+
.get('/foo')
1261+
.expect(200, 'saw GET /foo', function (err, res) {
1262+
assert.deepEqual(matchedRoutes, ['/foo'])
1263+
done(err)
1264+
})
1265+
})
1266+
1267+
it('should be undefined if there is not a match', function (done) {
1268+
var router = new Router()
1269+
var server = createServer(router)
1270+
var matchedRoutes
1271+
1272+
router.use(function (req, res, next) {
1273+
matchedRoutes = req.matchedRoutes
1274+
next()
1275+
})
1276+
1277+
request(server)
1278+
.get('/foo')
1279+
.expect(404, function (err, res) {
1280+
assert.strictEqual(matchedRoutes, undefined)
1281+
done(err)
1282+
})
1283+
})
1284+
1285+
it('should work with sub-routers', function (done) {
1286+
var router = new Router()
1287+
var fooRouter = new Router()
1288+
var server = createServer(router)
1289+
var matchedRoutes
1290+
1291+
router.use('/foo', fooRouter)
1292+
fooRouter.get('/bar', function (req, res, next) {
1293+
matchedRoutes = req.matchedRoutes
1294+
next()
1295+
})
1296+
router.use(saw)
1297+
1298+
request(server)
1299+
.get('/foo/bar')
1300+
.expect(200, 'saw GET /foo/bar', function (err, res) {
1301+
assert.deepEqual(matchedRoutes, ['/foo', '/bar'])
1302+
done(err)
1303+
})
1304+
})
1305+
1306+
it('should be undefined if sub-router did not match', function (done) {
1307+
var router = new Router()
1308+
var fooRouter = new Router()
1309+
var server = createServer(router)
1310+
var matchedRoutes
1311+
1312+
router.use('/foo', fooRouter)
1313+
fooRouter.get('/bar', function (req, res, next) {
1314+
matchedRoutes = req.matchedRoutes
1315+
next()
1316+
})
1317+
router.use(saw)
1318+
1319+
request(server)
1320+
.get('/foo/baz')
1321+
.expect(200, 'saw GET /foo/baz', function (err, res) {
1322+
assert.strictEqual(matchedRoutes, undefined)
1323+
done(err)
1324+
})
1325+
})
1326+
1327+
it('should work with regexp-defined routes', function (done) {
1328+
var router = new Router()
1329+
var server = createServer(router)
1330+
var matchedRoutes
1331+
var regexp = /fo+/
1332+
1333+
router.get(regexp, function (req, res, next) {
1334+
matchedRoutes = req.matchedRoutes
1335+
next()
1336+
})
1337+
router.use(saw)
1338+
1339+
request(server)
1340+
.get('/foo')
1341+
.expect(200, 'saw GET /foo', function (err, res) {
1342+
assert.deepEqual(matchedRoutes, [regexp])
1343+
done(err)
1344+
})
1345+
})
1346+
1347+
it('should support routes defined with arrays of paths', function (done) {
1348+
var router = new Router()
1349+
var server = createServer(router)
1350+
var matchedRoutes
1351+
1352+
router.get(['/foo', '/bar/:id'], function (req, res, next) {
1353+
matchedRoutes = req.matchedRoutes
1354+
next()
1355+
})
1356+
router.use(saw)
1357+
1358+
request(server)
1359+
.get('/foo')
1360+
.expect(200, 'saw GET /foo', function (err, res) {
1361+
if (err) {
1362+
return done(err)
1363+
}
1364+
assert.deepEqual(matchedRoutes, ['/foo'])
1365+
1366+
request(server)
1367+
.get('/bar/1')
1368+
.expect(200, 'saw GET /bar/1', function (err, res) {
1369+
if (err) {
1370+
return done(err)
1371+
}
1372+
assert.deepEqual(matchedRoutes, ['/bar/:id'])
1373+
done()
1374+
})
1375+
})
1376+
})
1377+
})
12461378
})
12471379

12481380
function helloWorld(req, res) {

0 commit comments

Comments
 (0)