Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Commit

Permalink
fix($route): correctly extract path params if path contains question …
Browse files Browse the repository at this point in the history
…mark or hash

The `routeToRegExp()` function, introduced by 840b5f0, could not extract
path params if the path contained question mark or hash. Although these
characters would normally be encoded in the path, they are decoded by
`$location.path()`, before being passed to the RegExp returned by
`routeToRegExp()`.

`routeToRegExp()` has to be able to deal with both encoded URL and
decoded path, because it is being shared between `ngRoute` and
`ngMocks`.

This commit fixes the issue, by introducing an `isUrl` option that
allows creating an appropriate RegExp for each usecase.
  • Loading branch information
susisu authored and gkalpak committed Aug 25, 2018
1 parent fa715ab commit 2ceeb73
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 7 deletions.
4 changes: 2 additions & 2 deletions src/ngMock/angular-mocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -1771,7 +1771,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* See {@link ngMock.$httpBackend#when `when`} for more info.
*/
$httpBackend.whenRoute = function(method, url) {
var pathObj = routeToRegExp(url, {caseInsensitiveMatch: true, ignoreTrailingSlashes: true});
var pathObj = routeToRegExp(url, {caseInsensitiveMatch: true, ignoreTrailingSlashes: true, isUrl: true});
return $httpBackend.when(method, pathObj.regexp, undefined, undefined, pathObj.keys);
};

Expand Down Expand Up @@ -1955,7 +1955,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
* See {@link ngMock.$httpBackend#expect `expect`} for more info.
*/
$httpBackend.expectRoute = function(method, url) {
var pathObj = routeToRegExp(url, {caseInsensitiveMatch: true, ignoreTrailingSlashes: true});
var pathObj = routeToRegExp(url, {caseInsensitiveMatch: true, ignoreTrailingSlashes: true, isUrl: true});
return $httpBackend.expect(method, pathObj.regexp, undefined, undefined, pathObj.keys);
};

Expand Down
10 changes: 5 additions & 5 deletions src/routeToRegExp.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/* global routeToRegExp: true */

/**
* @param path {string} path
* @param pathOrUrl {string} path or url
* @param opts {Object} options
* @return {?Object}
*
Expand All @@ -13,10 +13,10 @@
*
* Inspired by pathRexp in visionmedia/express/lib/utils.js.
*/
function routeToRegExp(path, opts) {
function routeToRegExp(pathOrUrl, opts) {
var keys = [];

var pattern = path
var pattern = pathOrUrl
.replace(/([().])/g, '\\$1')
.replace(/(\/)?:(\w+)(\*\?|[?*])?/g, function(_, slash, key, option) {
var optional = option === '?' || option === '*?';
Expand All @@ -25,7 +25,7 @@ function routeToRegExp(path, opts) {
slash = slash || '';
return (
(optional ? '(?:' + slash : slash + '(?:') +
(star ? '([^?#]+?)' : '([^/?#]+)') +
(opts.isUrl ? (star ? '([^?#]+?)' : '([^/?#]+)') : (star ? '(.+?)' : '([^/]+)')) +
(optional ? '?)?' : ')')
);
})
Expand All @@ -36,7 +36,7 @@ function routeToRegExp(path, opts) {
}

return {
originalPath: path,
originalPath: pathOrUrl,
keys: keys,
regexp: new RegExp(
'^' + pattern + '(?:[?#]|$)',
Expand Down
40 changes: 40 additions & 0 deletions test/ngRoute/routeParamsSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,45 @@ describe('$routeParams', function() {
});
});

it('should correctly extract path params containing hashes and/or question marks', function() {
module(function($routeProvider) {
$routeProvider.when('/foo/:bar', {});
$routeProvider.when('/zoo/:bar/:baz/:qux', {});
});

inject(function($location, $rootScope, $routeParams) {
$location.path('/foo/bar?baz');
$rootScope.$digest();
expect($routeParams).toEqual({bar: 'bar?baz'});

$location.path('/foo/bar?baz=val');
$rootScope.$digest();
expect($routeParams).toEqual({bar: 'bar?baz=val'});

$location.path('/foo/bar#baz');
$rootScope.$digest();
expect($routeParams).toEqual({bar: 'bar#baz'});

$location.path('/foo/bar?baz#qux');
$rootScope.$digest();
expect($routeParams).toEqual({bar: 'bar?baz#qux'});

$location.path('/foo/bar?baz=val#qux');
$rootScope.$digest();
expect($routeParams).toEqual({bar: 'bar?baz=val#qux'});

$location.path('/foo/bar#baz?qux');
$rootScope.$digest();
expect($routeParams).toEqual({bar: 'bar#baz?qux'});

$location.path('/zoo/bar?p1=v1#h1/baz?p2=v2#h2/qux?p3=v3#h3');
$rootScope.$digest();
expect($routeParams).toEqual({
bar: 'bar?p1=v1#h1',
baz: 'baz?p2=v2#h2',
qux: 'qux?p3=v3#h3'
});
});
});

});

0 comments on commit 2ceeb73

Please sign in to comment.