From 94039ef12c846bee8cf419d3ec065340b0200424 Mon Sep 17 00:00:00 2001 From: James Ide Date: Mon, 18 Jul 2022 17:18:20 -0700 Subject: [PATCH] URL-encode path parameters for Router.url (#116) The main breaking change from v8.x to v9.x was an upgrade to `path-to-regex`. [That PR](https://github.com/koajs/router/pull/71) alluded to a breaking change in encoding. Namely, parameters were not URL-encoded: parameters with safe special characters (like spaces) were not percent-encoded, and parameters with special characters that mean something in a URL, such as slashes (path separators) and question marks (query string delimiter). The motivation for this PR is to make URL-encoding be the default since typically the parameters provided to `Router.url` are plain, unencoded values. Should someone need an escape hatch, they could pass in `{ encode: null }` (I think) to disable the automatic encoding. Updated tests and docs. --- API.md | 2 +- lib/layer.js | 2 +- test/lib/layer.js | 6 ++++++ test/lib/router.js | 8 ++++++++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/API.md b/API.md index 8ca55fd..24e7c36 100644 --- a/API.md +++ b/API.md @@ -424,7 +424,7 @@ router ### Router.url(path, params) ⇒ String -Generate URL from url pattern and given `params`. +Generate URL from url pattern and given `params`. This method URL-encodes the parameters before including them in the URL. **Kind**: static method of [Router](#exp_module_koa-router--Router) diff --git a/lib/layer.js b/lib/layer.js index 5ad4d38..bb09bb9 100644 --- a/lib/layer.js +++ b/lib/layer.js @@ -119,7 +119,7 @@ Layer.prototype.url = function (params, options) { } } - const toPath = compile(url, options); + const toPath = compile(url, Object.assign({ encode: encodeURIComponent }, options)); let replaced; const tokens = parse(url); diff --git a/test/lib/layer.js b/test/lib/layer.js index f202be5..31c26a1 100644 --- a/test/lib/layer.js +++ b/test/lib/layer.js @@ -303,6 +303,12 @@ describe('Layer', function () { url.should.equal('/programming/how-to-node'); }); + it('escapes using encodeURIComponent()', function() { + const route = new Layer('/:category/:title', ['get'], [function () {}], {name: 'books'}); + const url = route.url({ category: 'programming', title: 'how to node & js/ts' }); + url.should.equal('/programming/how%20to%20node%20%26%20js%2Fts'); + }); + it('setPrefix method checks Layer for path', function () { const route = new Layer('/category', ['get'], [function () {}], { name: 'books' diff --git a/test/lib/router.js b/test/lib/router.js index 547bfb1..70a0993 100644 --- a/test/lib/router.js +++ b/test/lib/router.js @@ -1674,6 +1674,14 @@ describe('Router', function () { router.url('Picard').should.be.Error(); router.url(Symbol('books')).should.be.Error(); }); + + it('escapes using encodeURIComponent()', function() { + const url = Router.url( + '/:category/:title', + { category: 'programming', title: 'how to node & js/ts' } + ); + url.should.equal('/programming/how%20to%20node%20%26%20js%2Fts'); + }); }); describe('Router#param()', function () {