From 24c46c5fe218bf23e139d4ba0f99ba1121cfb67e Mon Sep 17 00:00:00 2001 From: Caitlin Potter Date: Thu, 24 Apr 2014 20:23:41 -0400 Subject: [PATCH] fix($location): parse query parameters which precede hash in hashbang mode This fix causes LocationHashbangUrl#$$rewrite() to move a pre-hash query string to after the hash. This, in turn, causes urlResolve() to correctly parse the query string, and report the correct dictionary. Closes #7239 --- src/ng/location.js | 24 ++++++++++++++++++++++-- test/ng/locationSpec.js | 20 ++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/ng/location.js b/src/ng/location.js index 3caa14e8de61..3c80aeac883e 100644 --- a/src/ng/location.js +++ b/src/ng/location.js @@ -168,8 +168,9 @@ function LocationHashbangUrl(appBase, hashPrefix) { */ this.$$parse = function(url) { var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url); + var tmp = beginsWith(hashPrefix, withoutBaseUrl); var withoutHashUrl = withoutBaseUrl.charAt(0) == '#' - ? beginsWith(hashPrefix, withoutBaseUrl) + ? tmp || (isUndefined(tmp) ? (withoutBaseUrl[1] === '?' && withoutBaseUrl.slice(1)) : '') : (this.$$html5) ? withoutBaseUrl : ''; @@ -235,7 +236,26 @@ function LocationHashbangUrl(appBase, hashPrefix) { }; this.$$rewrite = function(url) { - if(stripHash(appBase) == stripHash(url)) { + var stripHashBase = stripHash(appBase); + + // In HashbangMode, occasionally a query can be found preceeding the hash, + // however urlResolve only parses it as a query if it occurs after the hash. + // So, during the rewrite, it gets repositioned after the hash, if necessary. + var indexOfQuery = url.indexOf('?', stripHashBase.length), + indexOfHash = url.indexOf('#', stripHashBase.length); + + if (indexOfQuery >= 0 && indexOfHash >= 0 && indexOfQuery < indexOfHash) { + var preQuery = url.substr(indexOfQuery, indexOfHash - indexOfQuery); + var postQuery = url.indexOf('?', indexOfHash); + url = url.replace(preQuery, ''); + if (postQuery >= 0) { + url += '&' + preQuery.slice(1); + } else { + url += preQuery; + } + } + + if(stripHashBase == stripHash(url)) { return url; } }; diff --git a/test/ng/locationSpec.js b/test/ng/locationSpec.js index 37b78af0b6ea..9cf141fde5dc 100644 --- a/test/ng/locationSpec.js +++ b/test/ng/locationSpec.js @@ -396,6 +396,26 @@ describe('$location', function() { }); + it('search() should parse query parameters preceding hash prefix', function() { + url = new LocationHashbangUrl('http://server/base', '#!'); + url.$$parse(url.$$rewrite('http://server/base?a=b#!?c=d')); + expect(url.search()).toEqual({ + 'a': 'b', + 'c': 'd' + }); + }); + + + it('search() should parse query parameters preceeding hash fragment', function() { + url = new LocationHashbangUrl('http://server/base', '#!'); + url.$$parse(url.$$rewrite('http://server/base?a=b#?c=d')); + expect(url.search()).toEqual({ + 'a': 'b', + 'c': 'd' + }); + }); + + describe('encoding', function() { it('should encode special characters', function() {