Skip to content

Commit 4acf108

Browse files
wesleytodddougwilson
authored andcommitted
1 parent e0bbb53 commit 4acf108

File tree

5 files changed

+92
-79
lines changed

5 files changed

+92
-79
lines changed

HISTORY.md

+11
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,17 @@
33

44
55
* deps: parseurl@~1.3.3
6+
7+
- Add new `?`, `*`, and `+` parameter modifiers
8+
- Matching group expressions are only RegExp syntax.
9+
`(*)` is no longer valid and must be written as `(.*)`, for example.
10+
- Named matching groups no longer available by position in `req.params`.
11+
`/:foo(.*)` only captures as `req.params.foo` and not available as
12+
`req.parmas[0]`.
13+
- Regular expressions can only be used in a matching group.
14+
`/\\d+` is no longer valid and must be written as `/(\\d+)`.
15+
- Special `*` path segment behavior removed.
16+
`/foo/*/bar` will match a literal `*` as the middle segment.
617
718

819
2.0.0-alpha.1 / 2018-07-27

lib/layer.js

+16-9
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ var debug = require('debug')('router:layer')
2121
*/
2222

2323
var hasOwnProperty = Object.prototype.hasOwnProperty
24+
var TRAILING_SLASH_REGEXP = /\/+$/
2425

2526
/**
2627
* Expose `Layer`.
@@ -37,13 +38,13 @@ function Layer(path, options, fn) {
3738
var opts = options || {}
3839

3940
this.handle = fn
41+
this.keys = []
4042
this.name = fn.name || '<anonymous>'
4143
this.params = undefined
4244
this.path = undefined
43-
this.regexp = pathRegexp(path, this.keys = [], opts)
45+
this.regexp = pathRegexp((opts.strict ? path : loosen(path)), this.keys, opts)
4446

4547
// set fast path flags
46-
this.regexp.fast_star = path === '*'
4748
this.regexp.fast_slash = path === '/' && opts.end === false
4849
}
4950

@@ -132,13 +133,6 @@ Layer.prototype.match = function match(path) {
132133
return true
133134
}
134135

135-
// fast path for * (everything matched in a param)
136-
if (this.regexp.fast_star) {
137-
this.params = {'0': decode_param(path)}
138-
this.path = path
139-
return true
140-
}
141-
142136
// match the path
143137
match = this.regexp.exec(path)
144138
}
@@ -208,3 +202,16 @@ function isPromise (val) {
208202
typeof val === 'object' &&
209203
typeof val.then === 'function'
210204
}
205+
206+
/**
207+
* Loosens the given path for path-to-regexp matching.
208+
*/
209+
function loosen (path) {
210+
if (path instanceof RegExp) {
211+
return path
212+
}
213+
214+
return Array.isArray(path)
215+
? path.map(function (p) { return loosen(p) })
216+
: String(path).replace(TRAILING_SLASH_REGEXP, '')
217+
}

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"debug": "3.1.0",
1414
"methods": "~1.1.2",
1515
"parseurl": "~1.3.3",
16-
"path-to-regexp": "0.1.7",
16+
"path-to-regexp": "3.2.0",
1717
"setprototypeof": "1.2.0",
1818
"utils-merge": "1.0.1"
1919
},

test/req.params.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ describe('req.params', function () {
137137
})
138138
})
139139

140-
router.get('/*', hitParams(1))
140+
router.get('/(.*)', hitParams(1))
141141

142142
request(server)
143143
.get('/buzz')
@@ -156,7 +156,7 @@ describe('req.params', function () {
156156
})
157157
})
158158

159-
router.get('/*', hitParams(1))
159+
router.get('/(.*)', hitParams(1))
160160

161161
request(server)
162162
.get('/bar')

test/route.js

+62-67
Original file line numberDiff line numberDiff line change
@@ -655,18 +655,18 @@ describe('Router', function () {
655655
it('should work following a partial capture group', function (done) {
656656
var cb = after(2, done)
657657
var router = new Router()
658-
var route = router.route('/user(s)?/:user/:op')
658+
var route = router.route('/user(s?)/:user/:op')
659659
var server = createServer(router)
660660

661661
route.all(sendParams)
662662

663663
request(server)
664664
.get('/user/tj/edit')
665-
.expect(200, {'user': 'tj', 'op': 'edit'}, cb)
665+
.expect(200, { 0: '', user: 'tj', op: 'edit' }, cb)
666666

667667
request(server)
668668
.get('/users/tj/edit')
669-
.expect(200, {'0': 's', 'user': 'tj', 'op': 'edit'}, cb)
669+
.expect(200, { 0: 's', user: 'tj', op: 'edit' }, cb)
670670
})
671671

672672
it('should work inside literal paranthesis', function (done) {
@@ -699,132 +699,127 @@ describe('Router', function () {
699699
})
700700
})
701701

702-
describe('using "*"', function () {
703-
it('should capture everything', function (done) {
702+
describe('using ":name?"', function () {
703+
it('should name an optional parameter', function (done) {
704+
var cb = after(2, done)
704705
var router = new Router()
705-
var route = router.route('*')
706+
var route = router.route('/:foo?')
706707
var server = createServer(router)
707708

708709
route.all(sendParams)
709710

710711
request(server)
711-
.get('/foo/bar/baz')
712-
.expect(200, {'0': '/foo/bar/baz'}, done)
713-
})
714-
715-
it('should decode the capture', function (done) {
716-
var router = new Router()
717-
var route = router.route('*')
718-
var server = createServer(router)
719-
720-
route.all(sendParams)
712+
.get('/bar')
713+
.expect(200, { foo: 'bar' }, cb)
721714

722715
request(server)
723-
.get('/foo/%20/baz')
724-
.expect(200, {'0': '/foo/ /baz'}, done)
716+
.get('/')
717+
.expect(200, {}, cb)
725718
})
726719

727-
it('should capture everything with pre- and post-fixes', function (done) {
720+
it('should work in any segment', function (done) {
721+
var cb = after(2, done)
728722
var router = new Router()
729-
var route = router.route('/foo/*/bar')
723+
var route = router.route('/user/:foo?/delete')
730724
var server = createServer(router)
731725

732726
route.all(sendParams)
733727

734728
request(server)
735-
.get('/foo/1/2/3/bar')
736-
.expect(200, {'0': '1/2/3'}, done)
729+
.get('/user/bar/delete')
730+
.expect(200, { foo: 'bar' }, cb)
731+
732+
request(server)
733+
.get('/user/delete')
734+
.expect(200, {}, cb)
737735
})
736+
})
738737

739-
it('should capture greedly', function (done) {
738+
describe('using ":name*"', function () {
739+
it('should name a zero-or-more repeated parameter', function (done) {
740+
var cb = after(3, done)
740741
var router = new Router()
741-
var route = router.route('/foo/*/bar')
742+
var route = router.route('/:foo*')
742743
var server = createServer(router)
743744

744745
route.all(sendParams)
745746

746747
request(server)
747-
.get('/foo/bar/bar/bar')
748-
.expect(200, {'0': 'bar/bar'}, done)
749-
})
750-
751-
it('should be an optional capture', function (done) {
752-
var router = new Router()
753-
var route = router.route('/foo*')
754-
var server = createServer(router)
748+
.get('/')
749+
.expect(200, {}, cb)
755750

756-
route.all(sendParams)
751+
request(server)
752+
.get('/bar')
753+
.expect(200, { foo: 'bar' }, cb)
757754

758755
request(server)
759-
.get('/foo')
760-
.expect(200, {'0': ''}, done)
756+
.get('/fizz/buzz')
757+
.expect(200, { foo: 'fizz/buzz' }, cb)
761758
})
762759

763-
it('should require preceeding /', function (done) {
764-
var cb = after(2, done)
760+
it('should work in any segment', function (done) {
761+
var cb = after(3, done)
765762
var router = new Router()
766-
var route = router.route('/foo/*')
763+
var route = router.route('/user/:foo*/delete')
767764
var server = createServer(router)
768765

769766
route.all(sendParams)
770767

771768
request(server)
772-
.get('/foo')
773-
.expect(404, cb)
769+
.get('/user/delete')
770+
.expect(200, {}, cb)
771+
772+
request(server)
773+
.get('/user/bar/delete')
774+
.expect(200, { foo: 'bar' }, cb)
774775

775776
request(server)
776-
.get('/foo/')
777-
.expect(200, cb)
777+
.get('/user/fizz/buzz/delete')
778+
.expect(200, { foo: 'fizz/buzz' }, cb)
778779
})
780+
})
779781

780-
it('should work in a named parameter', function (done) {
781-
var cb = after(2, done)
782+
describe('using ":name+"', function () {
783+
it('should name a one-or-more repeated parameter', function (done) {
784+
var cb = after(3, done)
782785
var router = new Router()
783-
var route = router.route('/:foo(*)')
786+
var route = router.route('/:foo+')
784787
var server = createServer(router)
785788

786789
route.all(sendParams)
787790

788791
request(server)
789-
.get('/bar')
790-
.expect(200, {'0': 'bar', 'foo': 'bar'}, cb)
792+
.get('/')
793+
.expect(404, cb)
791794

792795
request(server)
793-
.get('/fizz/buzz')
794-
.expect(200, {'0': 'fizz/buzz', 'foo': 'fizz/buzz'}, cb)
795-
})
796-
797-
it('should work before a named parameter', function (done) {
798-
var router = new Router()
799-
var route = router.route('/*/user/:id')
800-
var server = createServer(router)
801-
802-
route.all(sendParams)
796+
.get('/bar')
797+
.expect(200, { foo: 'bar' }, cb)
803798

804799
request(server)
805-
.get('/poke/user/42')
806-
.expect(200, {'0': 'poke', 'id': '42'}, done)
800+
.get('/fizz/buzz')
801+
.expect(200, { foo: 'fizz/buzz' }, cb)
807802
})
808803

809-
it('should work within arrays', function (done) {
804+
it('should work in any segment', function (done) {
810805
var cb = after(3, done)
811806
var router = new Router()
812-
var route = router.route(['/user/:id', '/foo/*', '/:action'])
807+
var route = router.route('/user/:foo+/delete')
813808
var server = createServer(router)
814809

815810
route.all(sendParams)
816811

817812
request(server)
818-
.get('/user/42')
819-
.expect(200, {'id': '42'}, cb)
813+
.get('/user/delete')
814+
.expect(404, cb)
820815

821816
request(server)
822-
.get('/foo/bar')
823-
.expect(200, {'0': 'bar'}, cb)
817+
.get('/user/bar/delete')
818+
.expect(200, { foo: 'bar' }, cb)
824819

825820
request(server)
826-
.get('/poke')
827-
.expect(200, {'action': 'poke'}, cb)
821+
.get('/user/fizz/buzz/delete')
822+
.expect(200, { foo: 'fizz/buzz' }, cb)
828823
})
829824
})
830825
})

0 commit comments

Comments
 (0)