fix($location): allow hash fragments with hashPrefix in hash-bang location urls

Previously if there was a hash fragment but no hashPrefix we would throw an error.
Now we assume that the hash-bang path is empty and that the hash is a valid fragment.

This prevents unnecessary exceptions where we clear the hashBang path, say by
navigating back to the base url, where the $browser leaves an empty hash symbol
on the URL to ensure there is no browser reload.

BREAKING CHANGE:

We no longer throw an `ihshprfx` error if the URL after the base path
contains only a hash fragment.  Previously, if the base URL was `http://abc.com/base/`
and the hashPrefix is `!` then trying to parse `http://abc.com/base/#some-fragment`
would have thrown an error. Now we simply assume it is a normal fragment and
that the path is empty, resulting `$location.absUrl() === "http://abc.com/base/#!/#some-fragment"`.

This should not break any applications, but you can no longer rely on receiving the
`ihshprfx` error for paths that have the syntax above. It is actually more similar
to what currently happens for invalid extra paths anyway:  If the base URL
and hashPrfix are set up as above, then `http://abc.com/base/other/path` does not
throw an error but just ignores the extra path: `http://abc.com/base`.

Closes #9629
Closes #9635
Closes #10228
Closes #10308
This commit is contained in:
Peter Bacon Darwin
2014-12-03 10:43:21 +00:00
parent 10ac594809
commit 2dc34a9699
2 changed files with 35 additions and 12 deletions

View File

@@ -183,16 +183,25 @@ function LocationHashbangUrl(appBase, hashPrefix) {
*/
this.$$parse = function(url) {
var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
var withoutHashUrl = withoutBaseUrl.charAt(0) == '#'
? beginsWith(hashPrefix, withoutBaseUrl)
: (this.$$html5)
? withoutBaseUrl
: '';
var withoutHashUrl;
if (!isString(withoutHashUrl)) {
throw $locationMinErr('ihshprfx', 'Invalid url "{0}", missing hash prefix "{1}".', url,
hashPrefix);
if (withoutBaseUrl.charAt(0) === '#') {
// The rest of the url starts with a hash so we have
// got either a hashbang path or a plain hash fragment
withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl);
if (isUndefined(withoutHashUrl)) {
// There was no hashbang prefix so we just have a hash fragment
withoutHashUrl = withoutBaseUrl;
}
} else {
// There was no hashbang path nor hash fragment:
// If we are in HTML5 mode we use what is left as the path;
// Otherwise we ignore what is left
withoutHashUrl = this.$$html5 ? withoutBaseUrl : '';
}
parseAppUrl(withoutHashUrl, this);
this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);

View File

@@ -554,10 +554,24 @@ describe('$location', function() {
});
it('should throw error when invalid hashbang prefix given', function() {
expect(function() {
url.$$parse('http://www.server.org:1234/base#/path');
}).toThrowMinErr('$location', 'ihshprfx', 'Invalid url "http://www.server.org:1234/base#/path", missing hash prefix "#!".');
it('should insert default hashbang if a hash is given with no hashbang prefix', function() {
url.$$parse('http://www.server.org:1234/base#/path');
expect(url.absUrl()).toBe('http://www.server.org:1234/base#!#%2Fpath');
expect(url.hash()).toBe('/path');
expect(url.path()).toBe('');
url.$$parse('http://www.server.org:1234/base#');
expect(url.absUrl()).toBe('http://www.server.org:1234/base');
expect(url.hash()).toBe('');
expect(url.path()).toBe('');
});
it('should ignore extra path segments if no hashbang is given', function() {
url.$$parse('http://www.server.org:1234/base/extra/path');
expect(url.absUrl()).toBe('http://www.server.org:1234/base');
expect(url.path()).toBe('');
expect(url.hash()).toBe('');
});