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

Commit 81afe58

Browse files
committed
fix($location): use url resolve shim
1 parent 5e5a45f commit 81afe58

File tree

2 files changed

+95
-37
lines changed

2 files changed

+95
-37
lines changed

src/ng/location.js

+72-33
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,8 @@ function LocationHashbangInHtml5Url(appBase, hashPrefix) {
259259

260260
if ( appBase == stripHash(url) ) {
261261
return url;
262+
} else if ( (appUrl = beginsWith(appBaseNoFile + hashPrefix + '/', url)) ) {
263+
return appBase + hashPrefix + appUrl;
262264
} else if ( (appUrl = beginsWith(appBaseNoFile, url)) ) {
263265
return appBase + hashPrefix + appUrl;
264266
} else if ( appBaseNoFile === url + '/') {
@@ -675,39 +677,22 @@ function $LocationProvider(){
675677

676678
if (href && href.indexOf('://') < 0) { // Ignore absolute URLs
677679
var prefix = '#' + hashPrefix;
678-
var baseHrefNoFile = stripFile(baseHref);
679-
var appOnRoot = stripFile(appBase) == (serverBase(appBase) + '/');
680-
if (href[0] == '/' && (appOnRoot || (baseHref && beginsWith(baseHrefNoFile, href)))) {
681-
// absolute path - within base or when the app is on the root
682-
var hrefNoBase = baseHrefNoFile ? href.substr(baseHrefNoFile.length - 1) : href;
683-
absHref = appBase + prefix + hrefNoBase;
684-
} else if (href[0] != '/') { // Ignore absolute path outside of base
685-
var beginsWithPrefix = beginsWith(prefix, href);
686-
if (beginsWith(prefix + '/', href)) {
687-
// local anchor with absolute path
688-
absHref = appBase + href;
689-
} else if (!beginsWithPrefix && href[0] == '#') {
690-
// local anchor
691-
absHref = appBase + prefix + ($location.path() || '/') + href;
692-
} else if (!beginsWithPrefix && baseHref) {
693-
// local anchor and base[href] exists
694-
absHref = appBase + prefix + '/' + href;
695-
} else {
696-
href = beginsWithPrefix ? href.substr(prefix.length) : href;
697-
// relative path - join with current path
698-
var stack = $location.path().split("/"),
699-
parts = href.split("/");
700-
if (stack.length === 2 && !stack[1]) stack.length = 1;
701-
for (var i=0; i<parts.length; i++) {
702-
if (parts[i] == ".")
703-
continue;
704-
else if (parts[i] == "..")
705-
stack.pop();
706-
else if (parts[i].length)
707-
stack.push(parts[i]);
708-
}
709-
absHref = appBase + prefix + stack.join('/');
710-
}
680+
var appBaseNoFile = stripFile(appBase);
681+
var html5Url = appBase + $location.url().substr(1);
682+
var baseUri = baseHref ? urlResolveShim(baseHref, appBase) : html5Url;
683+
var appUrl;
684+
if (appUrl = beginsWith(prefix + '/', href)) {
685+
// hashbang beginning with / refers to appbase
686+
absHref = urlResolveShim(appBaseNoFile + appUrl);
687+
} else if (appUrl = beginsWith(prefix, href)) {
688+
// hashbang relative path
689+
absHref = urlResolveShim(appUrl, baseUri);
690+
} else if (href[0] == '#') {
691+
// local anchor
692+
absHref = appBase + prefix + ($location.path() || '/') + href;
693+
} else {
694+
// relative path
695+
absHref = urlResolveShim(href, baseUri);
711696
}
712697
}
713698
}
@@ -779,5 +764,59 @@ function $LocationProvider(){
779764
function afterLocationChange(oldUrl) {
780765
$rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);
781766
}
767+
768+
// Similar to URL(URL, base) of URLUtils
769+
function urlResolveShim(url, base) {
770+
var absHref;
771+
if (url.indexOf('//') >= 0) {
772+
absHref = url;
773+
} else if (url.charAt(0) === '/') {
774+
absHref = serverBase(base) + url;
775+
} else {
776+
absHref = stripFile(base) + url;
777+
}
778+
779+
var resolvedUrl = urlResolve(absHref);
780+
var hash = resolvedUrl.hash ? '#' + resolvedUrl.hash : '';
781+
var search = resolvedUrl.search;
782+
var path = resolvedUrl.pathname;
783+
var normalizedPath = normalizePath(path); // only for IE7 compatibility
784+
return serverBase(resolvedUrl.href) + normalizedPath + (search ? '?' + search : '') + hash;
785+
}
786+
787+
function normalizePath(path) {
788+
path = path || '';
789+
var inputSegments = path.split('/');
790+
var outputSegments = [];
791+
var inputSegment;
792+
for (var i = 0; i < inputSegments.length; i++) {
793+
inputSegment = inputSegments[i];
794+
795+
if ((inputSegment.length === 0)
796+
|| (inputSegment == '.')) {
797+
// Do nothing
798+
continue;
799+
} else if (inputSegment == '..') {
800+
if (outputSegments.length) {
801+
outputSegments.pop();
802+
}
803+
} else {
804+
outputSegments.push(inputSegment);
805+
}
806+
}
807+
808+
var outputSegment, output = '';
809+
for (i = 0; i < outputSegments.length; i++) {
810+
outputSegment = outputSegments[i];
811+
output += '/' + outputSegment;
812+
}
813+
814+
if (path.lastIndexOf('/') == path.length - 1) {
815+
// path.endsWith("/") || path.equals("")
816+
output += '/';
817+
}
818+
819+
return output;
820+
}
782821
}];
783822
}

test/ng/locationSpec.js

+23-4
Original file line numberDiff line numberDiff line change
@@ -1203,10 +1203,15 @@ describe('$location', function() {
12031203
initBrowser(false, true),
12041204
initLocation(),
12051205
function($browser, $location) {
1206+
$location.path('/some/');
1207+
expect($browser.url(), 'http://host.com/#!/some/');
1208+
browserTrigger(link, 'click');
1209+
expectRewriteTo($browser, 'http://host.com/#!/some/link');
1210+
12061211
$location.path('/some');
12071212
expect($browser.url(), 'http://host.com/#!/some');
12081213
browserTrigger(link, 'click');
1209-
expectRewriteTo($browser, 'http://host.com/#!/some/link');
1214+
expectRewriteTo($browser, 'http://host.com/#!/link');
12101215
}
12111216
);
12121217
});
@@ -1254,15 +1259,29 @@ describe('$location', function() {
12541259
});
12551260

12561261

1257-
it('should rewrite relative hashbang links when history enabled on old browser', function() {
1258-
configureService('#!link', true, false, true);
1262+
it('should replace current path when relative link begins with "/base/" and history enabled on old browser', function() {
1263+
configureService('/base/#!/link', true, false, true);
12591264
inject(
12601265
initBrowser(),
12611266
initLocation(),
12621267
function($browser, $location) {
12631268
$location.path('/some');
12641269
browserTrigger(link, 'click');
1265-
expectRewriteTo($browser, 'http://host.com/base/index.html#!/some/link');
1270+
expectRewriteTo($browser, 'http://host.com/base/index.html#!/link');
1271+
}
1272+
);
1273+
});
1274+
1275+
1276+
it('should rewrite relative hashbang links with respect to base when history enabled on old browser', function() {
1277+
configureService('#!link', true, false, true);
1278+
inject(
1279+
initBrowser(),
1280+
initLocation(),
1281+
function($browser, $location) {
1282+
$location.path('/some/');
1283+
browserTrigger(link, 'click');
1284+
expectRewriteTo($browser, 'http://host.com/base/index.html#!/link');
12661285
}
12671286
);
12681287
});

0 commit comments

Comments
 (0)