Skip to content

Commit

Permalink
URL-encode path parameters for Router.url
Browse files Browse the repository at this point in the history
The main breaking change from v8.x to v9.x was an upgrade to `path-to-regex`. [That PR](#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, docs, and the changelog.
  • Loading branch information
ide committed Mar 4, 2021
1 parent 344ba0b commit ca7bee0
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 8 deletions.
2 changes: 1 addition & 1 deletion API.md
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ router
<a name="module_koa-router--Router.url"></a>

#### Router.url(path, params) ⇒ <code>String</code>
Generate URL from url pattern and given `params`.
Generate URL from the given URL pattern and `params`. This method URL-encodes the parameters before including them in the URL.

**Kind**: static method of <code>[Router](#exp_module_koa-router--Router)</code>

Expand Down
7 changes: 7 additions & 0 deletions history.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
Next
==================

- [Breaking] URL-encode parameters passed to `Router.url` with `encodeURIComponent`.
- Previously, the parameters to insert in a URL were not encoded: `Router.url('/:x', { x: 'hello world' })` produced `"/hello world"` and `Router.url('/:x', { x: 'a/test?param#' })` would throw an error.
- Now, all parameters are safely URL-encoded by default: `Router.url('/:x', { x: 'hello world' })` produces `"/hello%20world"` and `Router.url('/:x', { x: 'a/test?param#' })` produces `"/a%2Ftest%3Fparam%23"`.

9.0.0 / 2020-04-09
==================

Expand Down
2 changes: 1 addition & 1 deletion lib/layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,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);
Expand Down
9 changes: 3 additions & 6 deletions test/lib/layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -239,11 +239,8 @@ describe('Layer', function() {

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' },
{ encode: encodeURIComponent }
);
url.should.equal('/programming/how%20to%20node');
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 () {
Expand All @@ -269,4 +266,4 @@ describe('Layer', function() {
prefix.path.should.equal(false)
});
});
});
});
8 changes: 8 additions & 0 deletions test/lib/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -1501,6 +1501,14 @@ describe('Router', function () {
.url("Picard", "Enterprise")
.should.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 () {
Expand Down

0 comments on commit ca7bee0

Please sign in to comment.