Skip to content

Commit

Permalink
Upgrade path to regexp (koajs#71)
Browse files Browse the repository at this point in the history
* upgrade path-to-regexp

* fix correct usage of Layer constructor

* Fix Layer#url options to handle encode

* Fix router#url tests

* Fix router prefix and index '/' route

https://github.com/pillarjs/path-to-regexp/blob/master/History.md#200--2017-08-23
> Explicitly handle trailing delimiters instead of trimming them
(e.g. /test/ is now treated as /test/ instead of /test when matching)
  • Loading branch information
Sinewyk authored Apr 9, 2020
1 parent f6bed2f commit 92df918
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 21 deletions.
19 changes: 12 additions & 7 deletions lib/layer.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
var debug = require('debug')('koa-router');
var pathToRegExp = require('path-to-regexp');
var { pathToRegexp, compile, parse } = require('path-to-regexp');
var uri = require('urijs');

module.exports = Layer;
Expand Down Expand Up @@ -45,7 +45,7 @@ function Layer(path, methods, middleware, opts) {
}

this.path = path;
this.regexp = pathToRegExp(path, this.paramNames, this.opts);
this.regexp = pathToRegexp(path, this.paramNames, this.opts);

debug('defined route %s %s', this.methods, this.opts.prefix + this.path);
};
Expand Down Expand Up @@ -117,8 +117,6 @@ Layer.prototype.captures = function (path) {
Layer.prototype.url = function (params, options) {
var args = params;
var url = this.path.replace(/\(\.\*\)/g, '');
var toPath = pathToRegExp.compile(url);
var replaced;

if (typeof params != 'object') {
args = Array.prototype.slice.call(arguments);
Expand All @@ -128,7 +126,10 @@ Layer.prototype.url = function (params, options) {
}
}

var tokens = pathToRegExp.parse(url);
var toPath = compile(url, options);
var replaced;

var tokens = parse(url);
var replace = {};

if (args instanceof Array) {
Expand Down Expand Up @@ -214,9 +215,13 @@ Layer.prototype.param = function (param, fn) {

Layer.prototype.setPrefix = function (prefix) {
if (this.path) {
this.path = prefix + this.path;
if (this.path !== '/' || this.opts.strict === true) {
this.path = prefix + this.path;
} else {
this.path = prefix;
}
this.paramNames = [];
this.regexp = pathToRegExp(this.path, this.paramNames, this.opts);
this.regexp = pathToRegexp(this.path, this.paramNames, this.opts);
}

return this;
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"http-errors": "^1.7.3",
"koa-compose": "^4.1.0",
"methods": "^1.1.2",
"path-to-regexp": "1.x",
"path-to-regexp": "^6.1.0",
"urijs": "^1.19.2"
},
"devDependencies": {
Expand Down
13 changes: 8 additions & 5 deletions test/lib/layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ describe('Layer', function() {
});

it('param with paramNames positive check', function () {
var route = new Layer('/:category/:title', ['get'], [function () {}], 'books');
var route = new Layer('/:category/:title', ['get'], [function () {}], {name: 'books'});
route.paramNames = [{
name: 'category',
}]
Expand All @@ -230,20 +230,23 @@ describe('Layer', function() {

describe('Layer#url()', function() {
it('generates route URL', function() {
var route = new Layer('/:category/:title', ['get'], [function () {}], 'books');
var route = new Layer('/:category/:title', ['get'], [function () {}], {name: 'books'});
var url = route.url({ category: 'programming', title: 'how-to-node' });
url.should.equal('/programming/how-to-node');
url = route.url('programming', 'how-to-node');
url.should.equal('/programming/how-to-node');
});

it('escapes using encodeURIComponent()', function() {
var route = new Layer('/:category/:title', ['get'], [function () {}], 'books');
var url = route.url({ category: 'programming', title: 'how to node' });
var route = new Layer('/:category/:title', ['get'], [function () {}], {name: 'books'});
var url = route.url(
{ category: 'programming', title: 'how to node' },
{ encode: encodeURIComponent }
);
url.should.equal('/programming/how%20to%20node');
});
it('setPrefix method checks Layer for path', function () {
const route = new Layer('/category', ['get'], [function () {}], 'books');
const route = new Layer('/category', ['get'], [function () {}], {name: 'books'});
route.path = '/hunter2'
const prefix = route.setPrefix('TEST')
prefix.path.should.equal('TEST/hunter2')
Expand Down
91 changes: 83 additions & 8 deletions test/lib/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -1107,7 +1107,7 @@ describe('Router', function () {
done();
}, error => done(error));
});

it('uses a same router middleware at given paths continuously - ZijianHe/koa-router#gh-244 gh-18', function (done) {
const app = new Koa();
const base = new Router({ prefix: '/api' });
Expand Down Expand Up @@ -1223,12 +1223,18 @@ describe('Router', function () {
router.get('books', '/:category/:title', function (ctx) {
ctx.status = 204;
});
var url = router.url('books', { category: 'programming', title: 'how to node' });
var url = router.url(
'books',
{ category: 'programming', title: 'how to node' },
{ encode: encodeURIComponent }
);
url.should.equal('/programming/how%20to%20node');
url = router.url('books', 'programming', 'how to node');
url = router.url('books', 'programming', 'how to node', {
encode: encodeURIComponent,
});
url.should.equal('/programming/how%20to%20node');
done();

});

it('generates URL for given route name within embedded routers', function (done) {
Expand All @@ -1245,9 +1251,15 @@ describe('Router', function () {
});
router.use(embeddedRouter.routes());
app.use(router.routes());
var url = router.url('chapters', { chapterName: 'Learning ECMA6', pageNumber: 123 });
var url = router.url(
'chapters',
{ chapterName: 'Learning ECMA6', pageNumber: 123 },
{ encode: encodeURIComponent }
);
url.should.equal('/books/chapters/Learning%20ECMA6/123');
url = router.url('chapters', 'Learning ECMA6', 123);
url = router.url('chapters', 'Learning ECMA6', 123, {
encode: encodeURIComponent,
});
url.should.equal('/books/chapters/Learning%20ECMA6/123');
done();
});
Expand All @@ -1269,7 +1281,11 @@ describe('Router', function () {
embeddedRouter.use(embeddedRouter2.routes());
router.use(embeddedRouter.routes());
app.use(router.routes());
var url = router.url('chapters', { chapterName: 'Learning ECMA6', pageNumber: 123 });
var url = router.url(
'chapters',
{ chapterName: 'Learning ECMA6', pageNumber: 123 },
{ encode: encodeURIComponent }
);
url.should.equal('/books/chapters/Learning%20ECMA6/pages/123');
done();
});
Expand Down Expand Up @@ -1836,6 +1852,61 @@ describe('Router', function () {
});
}
}

it(`prefix and '/' route behavior`, function(done) {
var app = new Koa();
var router = new Router({
strict: false,
prefix: '/foo'
});

var strictRouter = new Router({
strict: true,
prefix: '/bar'
})

router.get('/', function(ctx) {
ctx.body = '';
});

strictRouter.get('/', function(ctx) {
ctx.body = '';
});

app.use(router.routes());
app.use(strictRouter.routes());

var server = http.createServer(app.callback());

request(server)
.get('/foo')
.expect(200)
.end(function (err) {
if (err) return done(err);

request(server)
.get('/foo/')
.expect(200)
.end(function (err) {
if (err) return done(err);

request(server)
.get('/bar')
.expect(404)
.end(function (err) {
if (err) return done(err);

request(server)
.get('/bar/')
.expect(200)
.end(function (err) {
if (err) return done(err);
done();
});
});
});
});
})
});

describe('Static Router#url()', function () {
Expand All @@ -1845,7 +1916,11 @@ describe('Router', function () {
});

it('escapes using encodeURIComponent()', function () {
var url = Router.url('/:category/:title', { category: 'programming', title: 'how to node' });
var url = Router.url(
'/:category/:title',
{ category: 'programming', title: 'how to node' },
{ encode: encodeURIComponent }
);
url.should.equal('/programming/how%20to%20node');
});

Expand Down

0 comments on commit 92df918

Please sign in to comment.