-
Notifications
You must be signed in to change notification settings - Fork 27.5k
fix($location): consider baseHref in relative link for legacy browsers #8233
Conversation
Thanks for the PR! Please check the items below to help us merge this faster. See the contributing docs for more information.
If you need to make changes to your pull request, you can update the commit with Thanks again for your help! |
@thenikso It's certainly a tricky thing to get tests around, but it looks like there's plenty of helpers in locationSpec for setting this kind of stuff up. This spec is similar in spirit to what you're trying to test... have you tried something similar? https://github.com/angular/angular.js/blob/master/test/ng/locationSpec.js#L1162-L1190 |
@@ -668,6 +668,13 @@ function $LocationProvider(){ | |||
if (href.indexOf('://') < 0) { // Ignore absolute URLs | |||
var prefix = '#' + hashPrefix; | |||
if (href[0] == '/') { | |||
// Account for base href already present in appBase |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// use baseHref variable is fine
if (!baseHref && href.indexOf(baseHref) === 0) {
href = href.substr(baseHref.length);
if (!href || href[0] != '/') {
href = '/' + href;
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks! I've updated accordingly
Hi Jeffbcross, I have made a pinkr. Thanks |
I've added a test thanks to @timraymond suggestion. |
@thenikso I created a build of angular and angular-route from your commits, and the issue persists on my fork of @winsontam's plnkr on IE9: plnkr. |
I was talking with Igor about this today, there were a few nits regarding this, but I think we're good to just land this as is. With this, and a really tiny fix to prevent the I'm going to check this in today. |
@@ -668,6 +668,13 @@ function $LocationProvider(){ | |||
if (href.indexOf('://') < 0) { // Ignore absolute URLs | |||
var prefix = '#' + hashPrefix; | |||
if (href[0] == '/') { | |||
// Account for base href already present in appBase | |||
if (baseHref && href.indexOf(baseHref) === 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is quite right.
Assuming we have a base tag like <base href="http://www.google.com/foo/bar">
,
<a href="/baz" id="a">baz</a>
should resolve to http://www.google.com/baz
,
<a href="baz" id="a2">baz2</a>
should resolve to http://www.google.com/foo/baz
(not /foo/bar/baz
as you might expect, because the base tag doesnt' end with a slash)
The issues are, 1) we're not really correctly resolving relative to the baseURI for absolute references, and 2) we're not resolving relative URIs correctly this way at all, because this branch is only ever evaluated for absolute uris (uris beginning with a /
).
We need to fix this up
…-base absolute references
@caitp you are right, the relative URI case is not fixed at all in this PR. The logic for it should be to consider if the base tag ends with a
You also mentioned a @jeffbcross I'll take a look at your updated fiddle within the day. |
There are 2 bugs which cause that --- one of them is fixed in master right now, but the other one will happen whenever you try to rewrite a url that doesn't include the base href of the app (base href must be the same as app base, unfortunately :() |
The frustrating thing is that, because the appBase and baseHref are so closely tied in angular, it's not really possible for us to properly emulate relative urls WRT a base url --- to do so, the base path would need to be part of the virtual URL rather than part of the appBase --- otherwise there's no way we can correctly handle things like I kinda feel like just reverting would have been better. I'll take another look at it on monday |
FYI I modified @winsontam's plunkr in a way that reproduces this without requiring you to use IE9 here: http://plnkr.co/edit/UGPBOpHlHPghl6Q6wqXl?p=preview I also have a more detailed reproduction that shows the behaviour of relative paths and absolute paths here: http://stormy-fjord-8496.herokuapp.com/html5_no_history |
we've got all that, the problem is that this still does not match the behaviour of a history-enabled app. |
…` url BREAKING CHANGE (since 1.2.0 and 1.3.0-beta.1): Angular now requires a `<base>` tag when html5 mode of `$location` is enabled. Reasoning: Using html5 mode without a `<base href="...">` tag makes relative links for images, links, ... relative to the current url if the browser supports the history API. However, if the browser does not support the history API Angular falls back to using the `#`, and then all those relative links would be broken. The `<base>` tag is also needed when a deep url is loaded from the server, e.g. `http://server/some/page/url`. In that case, Angular needs to decide which part of the url is the base of the application, and which part is path inside of the application. To summarize: Now all relative links are always relative to the `<base>` tag. Exception (also a breaking change): Link tags whose `href` attribute starts with a `#` will only change the hash of the url, but nothing else (e.g. `<a href="#someAnchor">`). This is to make it easy to scroll to anchors inside a document. Related to angular#6162 Closes angular#8492 BREAKING CHANGE (since 1.2.17 and 1.3.0-beta.10): In html5 mode without a `<base>` tag on older browser that don't support the history API relative paths were adding up. E.g. clicking on `<a href="page1">` and then on `<a href="page2">` would produce `$location.path()==='/page1/page2'. The code that introduced this behavior was removed and Angular now also requires a `<base>` tag to be present when using html5 mode. Closes angular#8172, angular#8233
This should work now as expected as of 1.3.0-rc0, see 2294880 |
Hi guys, |
@tleruitte Just landed in v1.2.x branch... |
(but without enforcing the |
Request Type: bug
How to reproduce:
In a legacy browser that doesn't support HTML5 push state (ie: IE9) have the following:
$locationProvider.html5Mode(true).hashPrefix('!');
in app configuration;/foo
,/bar
in the$routeProvider
configuration;<base href="/en/">
in page headers;<a href="/en/foo">
in a link.When clicking a link, it is rewritten as:
http://host/en/#!/en/foo
Expected:
http://host/en/#!/foo
Component(s): $location
Impact: medium
Complexity: small
This issue is related to:
Other Comments:
I couldn't yet devise any test for covering this case. This fix concern a click handler on the
$rootElement
which (afaik) is not covered in the current tests.Please let me know if you find it reasonable and if you have ideas on how to test for it.
Thanks!