From d6c70b75b1af406a72b631efccb189bdd5318b67 Mon Sep 17 00:00:00 2001 From: Mu Yang Date: Fri, 24 Dec 2021 16:15:19 +0800 Subject: [PATCH] fix: double colon route issue (#219) --- node.js | 44 +++++++++++++++---------------------- test/issue-104.test.js | 23 +++++++++++++++++++ test/issue-175.test.js | 50 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 26 deletions(-) diff --git a/node.js b/node.js index 9c59e46b..0e2701ee 100644 --- a/node.js +++ b/node.js @@ -63,41 +63,33 @@ Node.prototype.addChild = function (node) { ) this.children[label] = node - this.numberOfChildren = Object.keys(this.children).length - const labels = Object.keys(this.children) - var parametricBrother = this.parametricBrother - for (var i = 0; i < labels.length; i++) { - const child = this.children[labels[i]] - if (child.label === ':') { + const nodeChildren = Object.values(this.children) + this.numberOfChildren = nodeChildren.length + + this._saveParametricBrother() + + return this +} + +Node.prototype._saveParametricBrother = function () { + let parametricBrother = this.parametricBrother + for (const child of Object.values(this.children)) { + if (child.prefix === ':') { parametricBrother = child break } } // Save the parametric brother inside static children - const iterate = (node) => { - if (!node) { - return - } - - if (node.kind !== this.types.STATIC) { - return - } - - if (node !== this) { - node.parametricBrother = parametricBrother || node.parametricBrother - } - - const labels = Object.keys(node.children) - for (var i = 0; i < labels.length; i++) { - iterate(node.children[labels[i]]) + if (parametricBrother) { + for (const child of Object.values(this.children)) { + if (child && child.kind === this.types.STATIC) { + child.parametricBrother = parametricBrother + child._saveParametricBrother(parametricBrother) + } } } - - iterate(this) - - return this } Node.prototype.reset = function (prefix) { diff --git a/test/issue-104.test.js b/test/issue-104.test.js index 695180f4..7993d48f 100644 --- a/test/issue-104.test.js +++ b/test/issue-104.test.js @@ -147,6 +147,29 @@ test('Mixed routes, url with parameter common prefix > 1', t => { t.same(findMyWay.find('GET', '/te/hellos/testy'), null) }) +test('Parent parametric brother should not rewrite child node parametric brother', t => { + t.plan(1) + const findMyWay = FindMyWay({ + defaultRoute: (req, res) => { + t.fail('Should not be defaultRoute') + } + }) + + findMyWay.on('GET', '/text/hello', (req, res, params) => { + res.end('{"hello":"world"}') + }) + + findMyWay.on('GET', '/text/:e/test', (req, res, params) => { + res.end('{"winter":"is here"}') + }) + + findMyWay.on('GET', '/:c', (req, res, params) => { + res.end('{"hello":"world"}') + }) + + t.same(findMyWay.find('GET', '/text/hellos/test').params, { e: 'hellos' }) +}) + test('Mixed parametric routes, with last defined route being static', t => { t.plan(4) const findMyWay = FindMyWay({ diff --git a/test/issue-175.test.js b/test/issue-175.test.js index 8a689bf9..129b1a50 100644 --- a/test/issue-175.test.js +++ b/test/issue-175.test.js @@ -29,3 +29,53 @@ test('exactly one match for static route with colon', t => { t.equal(findMyWay.find('GET', '/name:customVerb').handler, handler) t.equal(findMyWay.find('GET', '/name:test'), null) }) + +test('double colon is replaced with single colon, no parameters, same parent node name', t => { + t.plan(1) + const findMyWay = FindMyWay({ + defaultRoute: () => t.fail('should not be default route') + }) + + findMyWay.on('GET', '/name', () => { + t.fail('should not be parent route') + }) + + findMyWay.on('GET', '/name::customVerb', (req, res, params) => { + t.same(params, {}) + }) + + findMyWay.lookup({ method: 'GET', url: '/name:customVerb', headers: {} }, null) +}) + +test('double colon is replaced with single colon, default route, same parent node name', t => { + t.plan(1) + const findMyWay = FindMyWay({ + defaultRoute: () => t.ok('should be default route') + }) + + findMyWay.on('GET', '/name', () => { + t.fail('should not be parent route') + }) + + findMyWay.on('GET', '/name::customVerb', () => { + t.fail('should not be child route') + }) + + findMyWay.lookup({ method: 'GET', url: '/name:wrongCustomVerb', headers: {} }, null) +}) + +test('double colon is replaced with single colon, with parameters', t => { + t.plan(1) + const findMyWay = FindMyWay({ + defaultRoute: () => t.fail('should not be default route') + }) + + findMyWay.on('GET', '/name1::customVerb1/:param1/name2::customVerb2:param2', (req, res, params) => { + t.same(params, { + param1: 'value1', + param2: 'value2' + }) + }) + + findMyWay.lookup({ method: 'GET', url: '/name1:customVerb1/value1/name2:customVerb2value2', headers: {} }, null) +})