Skip to content

Commit 0f5ceca

Browse files
ajfranzoiagabegorelick
authored andcommitted
Store matched routes in request
1 parent dfd856c commit 0f5ceca

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
@@ -292,6 +292,11 @@ Router.prototype.handle = function handle(req, res, callback) {
292292
return next(layerError || err)
293293
}
294294

295+
if (layer.path) {
296+
req.matchedRoutes = req.matchedRoutes || []
297+
req.matchedRoutes.push(layer.matchedPath.path)
298+
}
299+
295300
if (route) {
296301
return layer.handle_request(req, res, next)
297302
}
@@ -347,7 +352,7 @@ Router.prototype.process_params = function process_params(layer, called, req, re
347352
var params = this.params
348353

349354
// captured parameters from the layer, keys and values
350-
var keys = layer.keys
355+
var keys = layer.matchedPath && layer.matchedPath.keys
351356

352357
// fast track
353358
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
/**
@@ -107,29 +119,39 @@ Layer.prototype.handle_request = function handle(req, res, next) {
107119

108120
Layer.prototype.match = function match(path) {
109121
var match
122+
var checkPath
110123

111124
if (path != null) {
112125
// fast path non-ending match for / (any path matches)
113-
if (this.regexp.fast_slash) {
126+
if (this.fastSlash) {
114127
this.params = {}
115128
this.path = ''
129+
this.matchedPath = this.paths[0]
116130
return true
117131
}
118132

119133
// fast path for * (everything matched in a param)
120-
if (this.regexp.fast_star) {
134+
if (this.fastStar) {
121135
this.params = {'0': decode_param(path)}
122136
this.path = path
137+
this.matchedPath = this.paths[0]
123138
return true
124139
}
125140

126141
// match the path
127-
match = this.regexp.exec(path)
142+
for (var i = 0; i < this.paths.length; i++) {
143+
checkPath = this.paths[i]
144+
if (match = checkPath.regexp.exec(path)) {
145+
this.matchedPath = checkPath
146+
break
147+
}
148+
}
128149
}
129150

130151
if (!match) {
131152
this.params = undefined
132153
this.path = undefined
154+
this.matchedPath = undefined
133155
return false
134156
}
135157

@@ -142,7 +164,7 @@ Layer.prototype.match = function match(path) {
142164
var params = this.params
143165

144166
for (var i = 1; i < match.length; i++) {
145-
var key = keys[i - 1]
167+
var key = this.matchedPath.keys[i - 1]
146168
var prop = key.name
147169
var val = decode_param(match[i])
148170

test/router.js

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,6 +1129,138 @@ describe('Router', function () {
11291129
.expect(200, 'saw GET /bar', done)
11301130
})
11311131
})
1132+
1133+
describe('req.matchedRoutes', function () {
1134+
it('should be set if there is a match', function (done) {
1135+
var router = new Router()
1136+
var server = createServer(router)
1137+
var matchedRoutes
1138+
1139+
router.get('/foo', function (req, res, next) {
1140+
matchedRoutes = req.matchedRoutes
1141+
next()
1142+
})
1143+
router.use(saw)
1144+
1145+
request(server)
1146+
.get('/foo')
1147+
.expect(200, 'saw GET /foo', function (err, res) {
1148+
assert.deepEqual(matchedRoutes, ['/foo'])
1149+
done(err)
1150+
})
1151+
})
1152+
1153+
it('should be undefined if there is not a match', function (done) {
1154+
var router = new Router()
1155+
var server = createServer(router)
1156+
var matchedRoutes
1157+
1158+
router.use(function (req, res, next) {
1159+
matchedRoutes = req.matchedRoutes
1160+
next()
1161+
})
1162+
1163+
request(server)
1164+
.get('/foo')
1165+
.expect(404, function (err, res) {
1166+
assert.strictEqual(matchedRoutes, undefined)
1167+
done(err)
1168+
})
1169+
})
1170+
1171+
it('should work with sub-routers', function (done) {
1172+
var router = new Router()
1173+
var fooRouter = new Router()
1174+
var server = createServer(router)
1175+
var matchedRoutes
1176+
1177+
router.use('/foo', fooRouter)
1178+
fooRouter.get('/bar', function (req, res, next) {
1179+
matchedRoutes = req.matchedRoutes
1180+
next()
1181+
})
1182+
router.use(saw)
1183+
1184+
request(server)
1185+
.get('/foo/bar')
1186+
.expect(200, 'saw GET /foo/bar', function (err, res) {
1187+
assert.deepEqual(matchedRoutes, ['/foo', '/bar'])
1188+
done(err)
1189+
})
1190+
})
1191+
1192+
it('should be undefined if sub-router did not match', function (done) {
1193+
var router = new Router()
1194+
var fooRouter = new Router()
1195+
var server = createServer(router)
1196+
var matchedRoutes
1197+
1198+
router.use('/foo', fooRouter)
1199+
fooRouter.get('/bar', function (req, res, next) {
1200+
matchedRoutes = req.matchedRoutes
1201+
next()
1202+
})
1203+
router.use(saw)
1204+
1205+
request(server)
1206+
.get('/foo/baz')
1207+
.expect(200, 'saw GET /foo/baz', function (err, res) {
1208+
assert.strictEqual(matchedRoutes, undefined)
1209+
done(err)
1210+
})
1211+
})
1212+
1213+
it('should work with regexp-defined routes', function (done) {
1214+
var router = new Router()
1215+
var server = createServer(router)
1216+
var matchedRoutes
1217+
var regexp = /fo+/
1218+
1219+
router.get(regexp, function (req, res, next) {
1220+
matchedRoutes = req.matchedRoutes
1221+
next()
1222+
})
1223+
router.use(saw)
1224+
1225+
request(server)
1226+
.get('/foo')
1227+
.expect(200, 'saw GET /foo', function (err, res) {
1228+
assert.deepEqual(matchedRoutes, [regexp])
1229+
done(err)
1230+
})
1231+
})
1232+
1233+
it('should support routes defined with arrays of paths', function (done) {
1234+
var router = new Router()
1235+
var server = createServer(router)
1236+
var matchedRoutes
1237+
1238+
router.get(['/foo', '/bar/:id'], function (req, res, next) {
1239+
matchedRoutes = req.matchedRoutes
1240+
next()
1241+
})
1242+
router.use(saw)
1243+
1244+
request(server)
1245+
.get('/foo')
1246+
.expect(200, 'saw GET /foo', function (err, res) {
1247+
if (err) {
1248+
return done(err)
1249+
}
1250+
assert.deepEqual(matchedRoutes, ['/foo'])
1251+
1252+
request(server)
1253+
.get('/bar/1')
1254+
.expect(200, 'saw GET /bar/1', function (err, res) {
1255+
if (err) {
1256+
return done(err)
1257+
}
1258+
assert.deepEqual(matchedRoutes, ['/bar/:id'])
1259+
done()
1260+
})
1261+
})
1262+
})
1263+
})
11321264
})
11331265

11341266
function helloWorld(req, res) {

0 commit comments

Comments
 (0)