From 1c2ed71eb63932a965f9aab70471fb5f335fd5d4 Mon Sep 17 00:00:00 2001 From: Ed Epstein Date: Thu, 23 Mar 2017 23:47:38 -0700 Subject: [PATCH] (fix): merge URI query into fragment in non-html5 $location mode. Angular does not currently include the non-fragment query portion Of URLs in non-html5 $location mode. This commit merges the fragment Query, if present, with the non-fragment query if it exists. See #15856 --- src/ng/location.js | 25 +++++++++++++++++++++++++ test/ng/locationSpec.js | 27 ++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/ng/location.js b/src/ng/location.js index bf1858079c3f..fca09af66e67 100644 --- a/src/ng/location.js +++ b/src/ng/location.js @@ -70,6 +70,10 @@ function stripBaseUrl(base, url) { } } +function findSearch(url) { + var index = url.indexOf('?'); + return index === -1 ? false : url.substr(index + 1, url.indexOf('#') === -1 ? url.length : url.indexOf('#') - index - 1); +} function stripHash(url) { var index = url.indexOf('#'); @@ -206,6 +210,27 @@ function LocationHashbangUrl(appBase, appBaseNoFile, hashPrefix) { withoutHashUrl = withoutBaseUrl; } + // apply any search params from the actual url to the withoutHashUrl + // appBase will already have the hash taken off at this point. + var paramRewrittenUrl = withoutHashUrl; + var search = findSearch(appBase); + if (search !== false) { + var indexOfAppFragment = withoutHashUrl.indexOf('#'); + if (indexOfAppFragment !== -1) { + paramRewrittenUrl = withoutHashUrl.substr(0, indexOfAppFragment) + '?' + search + withoutHashUrl.substr(indexOfAppFragment, withoutHashUrl.length); + } else { + paramRewrittenUrl = withoutHashUrl + '?' + search; + } + // we know that there is a query param before the hash, as in the RFC. + if (findSearch(withoutHashUrl) !== false) { + var indexOfAppPath = withoutHashUrl.indexOf('?'); + if (indexOfAppPath !== -1) { + paramRewrittenUrl = withoutHashUrl.substr(0, indexOfAppPath + 1) + search + '&' + withoutHashUrl.substr(indexOfAppPath + 1, withoutHashUrl.length); + } + } + } + withoutHashUrl = paramRewrittenUrl; + } else { // There was no hashbang path nor hash fragment: // If we are in HTML5 mode we use what is left as the path; diff --git a/test/ng/locationSpec.js b/test/ng/locationSpec.js index 3ab431234dff..8e356f7da2f5 100644 --- a/test/ng/locationSpec.js +++ b/test/ng/locationSpec.js @@ -527,14 +527,39 @@ describe('$location', function() { it('should preserve query params in base', function() { var locationUrl = new LocationHashbangUrl('http://www.server.org:1234/base?base=param', 'http://www.server.org:1234/', '#'); locationUrl.$$parse('http://www.server.org:1234/base?base=param#/path?a=b&c#hash'); - expect(locationUrl.absUrl()).toBe('http://www.server.org:1234/base?base=param#/path?a=b&c#hash'); + expect(locationUrl.absUrl()).toBe('http://www.server.org:1234/base?base=param#/path?base=param&a=b&c#hash'); + expect(locationUrl.search()).toEqual({base: 'param', a: 'b', c: true}); locationUrl.path('/new/path'); locationUrl.search({one: 1}); locationUrl.hash('hhh'); expect(locationUrl.absUrl()).toBe('http://www.server.org:1234/base?base=param#/new/path?one=1#hhh'); }); + it('should copy query params to fragment', function() { + var locationUrl = new LocationHashbangUrl('http://www.server.org:1234/base?base=param', 'http://www.server.org:1234/', '#'); + locationUrl.$$parse('http://www.server.org:1234/base?base=param#/path'); + + expect(locationUrl.absUrl()).toBe('http://www.server.org:1234/base?base=param#/path?base=param'); + + expect(locationUrl.search()).toEqual({base: 'param'}); + locationUrl.path('/new/path'); + locationUrl.search({one: 1}); + locationUrl.hash('hhh'); + expect(locationUrl.absUrl()).toBe('http://www.server.org:1234/base?base=param#/new/path?one=1#hhh'); + + locationUrl.$$parse('http://www.server.org:1234/base?base=param#/path#trailingHash'); + + expect(locationUrl.absUrl()).toBe('http://www.server.org:1234/base?base=param#/path?base=param#trailingHash'); + + expect(locationUrl.search()).toEqual({base: 'param'}); + locationUrl.path('/new/path'); + locationUrl.search({one: 1}); + locationUrl.hash('hhh'); + expect(locationUrl.absUrl()).toBe('http://www.server.org:1234/base?base=param#/new/path?one=1#hhh'); + + }); + it('should prefix path with forward-slash', function() { var locationUrl = new LocationHashbangUrl('http://host.com/base', 'http://host.com/', '#');