From 5b73129ae7119b5d25879be4e0760ea308fb6cbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Fantone?= Date: Mon, 15 Nov 2021 19:58:18 +0000 Subject: [PATCH 1/7] deps: path-to-regexp@6.2.0 --- lib/layer.js | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/layer.js b/lib/layer.js index 73f7d69..b514344 100644 --- a/lib/layer.js +++ b/lib/layer.js @@ -13,7 +13,7 @@ */ var isPromise = require('is-promise') -var pathRegexp = require('path-to-regexp') +var pathToRegexp = require('path-to-regexp').pathToRegexp /** * Module variables. @@ -41,7 +41,7 @@ function Layer (path, options, fn) { this.name = fn.name || '' this.params = undefined this.path = undefined - this.regexp = pathRegexp((opts.strict ? path : loosen(path)), this.keys, opts) + this.regexp = pathToRegexp((opts.strict ? path : loosen(path)), this.keys, opts) // set fast path flags this.regexp._slash = path === '/' && opts.end === false diff --git a/package.json b/package.json index b18ef68..ba33d14 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "is-promise": "4.0.0", "methods": "~1.1.2", "parseurl": "~1.3.3", - "path-to-regexp": "3.2.0", + "path-to-regexp": "6.2.0", "setprototypeof": "1.2.0", "utils-merge": "1.0.1" }, From 34fe7250d71cf0fc34d5f3a856a10cc441eeb4df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Fantone?= Date: Mon, 15 Nov 2021 23:24:41 +0000 Subject: [PATCH 2/7] test: add test for path-to-regexp@6.2.0 features --- test/route.js | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) diff --git a/test/route.js b/test/route.js index 5bfe75b..ecffdc7 100644 --- a/test/route.js +++ b/test/route.js @@ -860,6 +860,54 @@ describe('Router', function () { }) }) + describe('using "{:name}"', function () { + it('should allow defining custom prefixes', function (done) { + var cb = after(3, done) + var router = new Router() + var route = router.route('/{$:foo}{$:bar}?') + var server = createServer(router) + + route.all(sendParams) + + request(server) + .get('/bar') + .expect(404, cb) + + request(server) + .get('/$bar') + .expect(200, { foo: 'bar' }, cb) + + request(server) + .get('/$bar$fizz') + .expect(200, { foo: 'bar', bar: 'fizz' }, cb) + }) + + it('should work in any segment', function (done) { + var cb = after(4, done) + var router = new Router() + var route = router.route('/user/:foo?{-:bar}?{-:baz}?') + var server = createServer(router) + + route.all(sendParams) + + request(server) + .get('/user') + .expect(200, cb) + + request(server) + .get('/user/delete') + .expect(200, { foo: 'delete' }, cb) + + request(server) + .get('/user/delete-fizz') + .expect(200, { foo: 'delete', bar: 'fizz' }, cb) + + request(server) + .get('/user/delete-fizz-buzz') + .expect(200, { foo: 'delete', bar: 'fizz', baz: 'buzz' }, cb) + }) + }) + describe('using "(regexp)"', function () { it('should add capture group using regexp', function (done) { var cb = after(2, done) @@ -898,7 +946,112 @@ describe('Router', function () { .get('/foo:n42') .expect(200, { 0: 'foo:n42' }, cb) }) + + it('should allow optional capturing group', function (done) { + var cb = after(4, done) + var router = new Router() + var route = router.route('/user(s)?/:foo') + var server = createServer(router) + + route.all(sendParams) + + request(server) + .get('/user') + .expect(404, cb) + + request(server) + .get('/users') + .expect(404, cb) + + request(server) + .get('/user/bar') + .expect(200, { foo: 'bar' }, cb) + + request(server) + .get('/users/bar') + .expect(200, { 0: 's', foo: 'bar' }, cb) + }) + + it('should work in any segment', function (done) { + var cb = after(4, done) + var router = new Router() + var route = router.route('/users/image(s)?/:foo') + var server = createServer(router) + + route.all(sendParams) + + request(server) + .get('/users/image') + .expect(404, cb) + + request(server) + .get('/users/images') + .expect(404, cb) + + request(server) + .get('/users/image/1234') + .expect(200, { foo: '1234' }, cb) + + request(server) + .get('/users/images/1234') + .expect(200, { 0: 's', foo: '1234' }, cb) + }) }) + + // Named capturing groups are available from Node `10.0.0` and up + if (runningOnNodeMajorVersionGreaterOrEqualThan(10)) { + describe('using "(?)"', function () { + it('should allow defining capturing groups using regexps', function (done) { + var cb = after(3, done) + var router = new Router() + var route = router.route(/\/(?.+)/) + var server = createServer(router) + + route.all(sendParams) + + request(server) + .get('/') + .expect(404, cb) + + request(server) + .get('/foo/bar') + .expect(200, { name: 'foo/bar' }, cb) + + request(server) + .get('/foo') + .expect(200, { name: 'foo' }, cb) + }) + + it('should work with multiple named groups in the same segment', function (done) { + var cb = after(5, done) + var router = new Router() + var route = router.route(/\/(?.*).(?html|pdf|json)/) + var server = createServer(router) + + route.all(sendParams) + + request(server) + .get('/foo') + .expect(404, cb) + + request(server) + .get('/foo.xml') + .expect(404, cb) + + request(server) + .get('/foo.html') + .expect(200, { filename: 'foo', ext: 'html' }, cb) + + request(server) + .get('/bar.pdf') + .expect(200, { filename: 'bar', ext: 'pdf' }, cb) + + request(server) + .get('/baz.json') + .expect(200, { filename: 'baz', ext: 'json' }, cb) + }) + }) + } }) }) }) @@ -921,3 +1074,7 @@ function sendParams (req, res) { res.setHeader('Content-Type', 'application/json') res.end(JSON.stringify(req.params)) } + +function runningOnNodeMajorVersionGreaterOrEqualThan (version) { + return Number(process.versions.node.split('.')[0]) >= Number(version) +} From ecacd4ce68776b493bd9087d6f7bdfaee0cd4bb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Fantone?= Date: Mon, 15 Nov 2021 23:53:12 +0000 Subject: [PATCH 3/7] test: cover matching literal parenthesis in capturing groups --- test/route.js | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/test/route.js b/test/route.js index ecffdc7..a5f05b5 100644 --- a/test/route.js +++ b/test/route.js @@ -687,7 +687,7 @@ describe('Router', function () { .expect(200, { 0: 's', user: 'tj', op: 'edit' }, cb) }) - it('should work inside literal paranthesis', function (done) { + it('should work inside literal parenthesis', function (done) { var router = new Router() var route = router.route('/:user\\(:op\\)') var server = createServer(router) @@ -699,6 +699,27 @@ describe('Router', function () { .expect(200, { user: 'tj', op: 'edit' }, done) }) + it('should allow matching literal parenthesis within a group', function (done) { + var cb = after(3, done) + var router = new Router() + var route = router.route('/:user([a-z\\(\\)]+)') + var server = createServer(router) + + route.all(sendParams) + + request(server) + .get('/1234') + .expect(404, cb) + + request(server) + .get('/foo') + .expect(200, { user: 'foo' }, cb) + + request(server) + .get('/(foo)') + .expect(200, { user: '(foo)' }, cb) + }) + it('should work within arrays', function (done) { var cb = after(2, done) var router = new Router() From 1f4240c4dfb52f27f0dfbe51840a0f4865c848ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Fantone?= Date: Wed, 17 Nov 2021 15:03:50 +0000 Subject: [PATCH 4/7] docs: add path-to-regexp update changes to history --- HISTORY.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 1e1e91c..cdc1f9c 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -4,6 +4,11 @@ This incorporates all changes after 1.3.5 up to 1.3.7. * Add support for returned, rejected Promises to `router.param` + * deps: path-to-regexp@6.2.0 + - Support for **named capturing groups** in paths using `RegExp`, i.e.: `/\/(?.+)/` would result in `req.params.group` being populated. + - Custom **prefix and suffix groups** using `{}`, e.g.: `/:entity{-:action}?` would match `/user` and `/user-delete`. + - Unbalanced patterns would now produce an error: `/test(foo` previously would worked, now it expects either `(` to be closed or the character to be escaped for the previous behavior, e.g. `/test\\(foo`. + - Just like with parentheses since `2.0.0-beta.1`, bracket literals now require escaping, i.e.: `/user{:id}` no longer matches `/user{42}` as before unless written as `/user\\{:id\\}`. 2.0.0-beta.1 / 2020-03-29 ========================= From 54aa5ac752010c780274c989a93f91d83e47303d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Fantone?= Date: Sun, 12 Dec 2021 02:08:14 +0000 Subject: [PATCH 5/7] docs: reword unbalanced parens change in history --- HISTORY.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index cdc1f9c..2f7125f 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -7,8 +7,8 @@ This incorporates all changes after 1.3.5 up to 1.3.7. * deps: path-to-regexp@6.2.0 - Support for **named capturing groups** in paths using `RegExp`, i.e.: `/\/(?.+)/` would result in `req.params.group` being populated. - Custom **prefix and suffix groups** using `{}`, e.g.: `/:entity{-:action}?` would match `/user` and `/user-delete`. - - Unbalanced patterns would now produce an error: `/test(foo` previously would worked, now it expects either `(` to be closed or the character to be escaped for the previous behavior, e.g. `/test\\(foo`. - - Just like with parentheses since `2.0.0-beta.1`, bracket literals now require escaping, i.e.: `/user{:id}` no longer matches `/user{42}` as before unless written as `/user\\{:id\\}`. + - Unbalanced patterns now produce an error: `/test(foo` previously worked, but now it expects `(` to be escaped for the previous behavior, e.g. `/test\\(foo`. + - Just like with parentheses since `2.0.0-beta.1`, bracket literals now require escaping, i.e.: `/user{:id}` no longer matches `/user{42}` as before unless written as `/user\\{:id\\}`. 2.0.0-beta.1 / 2020-03-29 ========================= From 537e97f42fe552d768408b32764c02e095cca765 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 24 Feb 2023 13:06:59 -0500 Subject: [PATCH 6/7] tests: show unsupported tests as skipped --- test/route.js | 83 +++++++++++++++++++++++++-------------------------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/test/route.js b/test/route.js index a5f05b5..344ad77 100644 --- a/test/route.js +++ b/test/route.js @@ -14,6 +14,8 @@ var shouldHitHandle = utils.shouldHitHandle var shouldNotHaveBody = utils.shouldNotHaveBody var shouldNotHitHandle = utils.shouldNotHitHandle +// Named capturing groups are available from Node `10.0.0` and up +var describeCaptureGroups = runningOnNodeMajorVersionGreaterOrEqualThan(10) ? describe : describe.skip var describePromises = global.Promise ? describe : describe.skip describe('Router', function () { @@ -1019,60 +1021,57 @@ describe('Router', function () { }) }) - // Named capturing groups are available from Node `10.0.0` and up - if (runningOnNodeMajorVersionGreaterOrEqualThan(10)) { - describe('using "(?)"', function () { - it('should allow defining capturing groups using regexps', function (done) { - var cb = after(3, done) - var router = new Router() - var route = router.route(/\/(?.+)/) - var server = createServer(router) + describeCaptureGroups('using "(?)"', function () { + it('should allow defining capturing groups using regexps', function (done) { + var cb = after(3, done) + var router = new Router() + var route = router.route(/\/(?.+)/) + var server = createServer(router) - route.all(sendParams) + route.all(sendParams) - request(server) - .get('/') - .expect(404, cb) + request(server) + .get('/') + .expect(404, cb) - request(server) - .get('/foo/bar') - .expect(200, { name: 'foo/bar' }, cb) + request(server) + .get('/foo/bar') + .expect(200, { name: 'foo/bar' }, cb) - request(server) - .get('/foo') - .expect(200, { name: 'foo' }, cb) - }) + request(server) + .get('/foo') + .expect(200, { name: 'foo' }, cb) + }) - it('should work with multiple named groups in the same segment', function (done) { - var cb = after(5, done) - var router = new Router() - var route = router.route(/\/(?.*).(?html|pdf|json)/) - var server = createServer(router) + it('should work with multiple named groups in the same segment', function (done) { + var cb = after(5, done) + var router = new Router() + var route = router.route(/\/(?.*).(?html|pdf|json)/) + var server = createServer(router) - route.all(sendParams) + route.all(sendParams) - request(server) - .get('/foo') - .expect(404, cb) + request(server) + .get('/foo') + .expect(404, cb) - request(server) - .get('/foo.xml') - .expect(404, cb) + request(server) + .get('/foo.xml') + .expect(404, cb) - request(server) - .get('/foo.html') - .expect(200, { filename: 'foo', ext: 'html' }, cb) + request(server) + .get('/foo.html') + .expect(200, { filename: 'foo', ext: 'html' }, cb) - request(server) - .get('/bar.pdf') - .expect(200, { filename: 'bar', ext: 'pdf' }, cb) + request(server) + .get('/bar.pdf') + .expect(200, { filename: 'bar', ext: 'pdf' }, cb) - request(server) - .get('/baz.json') - .expect(200, { filename: 'baz', ext: 'json' }, cb) - }) + request(server) + .get('/baz.json') + .expect(200, { filename: 'baz', ext: 'json' }, cb) }) - } + }) }) }) }) From 83b4830acfa40db40a8c2859a0967a19f84e0c30 Mon Sep 17 00:00:00 2001 From: Douglas Christopher Wilson Date: Fri, 24 Feb 2023 13:11:43 -0500 Subject: [PATCH 7/7] tests: use feature detetion for named capture groups --- test/route.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/test/route.js b/test/route.js index 344ad77..ae67fda 100644 --- a/test/route.js +++ b/test/route.js @@ -14,8 +14,7 @@ var shouldHitHandle = utils.shouldHitHandle var shouldNotHaveBody = utils.shouldNotHaveBody var shouldNotHitHandle = utils.shouldNotHitHandle -// Named capturing groups are available from Node `10.0.0` and up -var describeCaptureGroups = runningOnNodeMajorVersionGreaterOrEqualThan(10) ? describe : describe.skip +var describeNamedCaptureGroups = supportsRegExp('(?.)') ? describe : describe.skip var describePromises = global.Promise ? describe : describe.skip describe('Router', function () { @@ -1021,7 +1020,7 @@ describe('Router', function () { }) }) - describeCaptureGroups('using "(?)"', function () { + describeNamedCaptureGroups('using "(?)"', function () { it('should allow defining capturing groups using regexps', function (done) { var cb = after(3, done) var router = new Router() @@ -1095,6 +1094,10 @@ function sendParams (req, res) { res.end(JSON.stringify(req.params)) } -function runningOnNodeMajorVersionGreaterOrEqualThan (version) { - return Number(process.versions.node.split('.')[0]) >= Number(version) +function supportsRegExp (source) { + try { + return RegExp(source).source !== '' + } catch (e) { + return false + } }