Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions lib/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,23 @@ function Route(spec) {

Route.prototype = Object.create(null);

/**
* Escape asterisks, open parantheses and closed parantheses.
* This is necessary because they are valid parts of an URL
* but reserved characters in route-parser.
* @param {string} path the path to escape
* @return {string} The escaped path, containing %2A instead
* of *, %28 instead of ( and %29 instead of )
*/
function escape(path) {
return path.replace(/\*/g, '%2A')
.replace(/\(/g, '%28')
.replace(/\)/g, '%29');
}

/**
* Match a path against this route, returning the matched parameters if
* it matches, false if not.
* it matches, false if not. Escapes asterisks in route.
* @example
* var route = new Route('/this/is/my/route')
* route.match('/this/is/my/route') // -> {}
Expand All @@ -50,7 +64,8 @@ Route.prototype = Object.create(null);
*/
Route.prototype.match = function (path) {
var re = RegexpVisitor.visit(this.ast);
var matched = re.match(path);
var escapedPath = escape(path);
var matched = re.match(escapedPath);

return matched !== null ? matched : false;
};
Expand Down
14 changes: 14 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,16 @@ describe('Route', function () {
var route = RouteParser('/*a/foo/*b');
assert.deepEqual(route.match('/zoo/woo/foo/bar/baz'), { a: 'zoo/woo', b: 'bar/baz' });
});

it('escapes asterisk in route', function () {
var route = RouteParser('/foo?bar=%2Atest&*a=splat');
assert.deepEqual(route.match('/foo?bar=*test&marker=splat'), { a: 'marker' });
});

it('escapes multiple asterisks', function () {
var route = RouteParser('/foo?bar=%2Atest&*a=splat&foo=%2Abar');
assert.deepEqual(route.match('/foo?bar=*test&marker=splat&foo=*bar'), { a: 'marker' });
});
});

describe('mixed', function () {
Expand Down Expand Up @@ -105,6 +115,10 @@ describe('Route', function () {
var route = RouteParser('/things/(option/:first)');
assert.deepEqual(route.match('/things/option/bar'), { first: 'bar' });
});
it('escapes parantheses in route', function () {
var route = RouteParser('/foo/(option/:first)');
assert.deepEqual(route.match('/foo/option/bar()'), { first: 'bar()' });
});

describe('nested', function () {
it('allows nested', function () {
Expand Down