-
Notifications
You must be signed in to change notification settings - Fork 27.4k
fix($location): links should respect absolute paths and base href when in html5mode #9126
Conversation
…cy browsers This CL fixes problems and adds test cases for changes from #6421. Changes include fixing the algorithm for preprocessing href attribute values, as well as supporting xlink:href attributes. Credit for the original URL parsing algorithm still goes to @richardcrichardc. Good work, champ!
this isn't going to be merged IMHO, it will make replacing the current broken behaviour with the correct behaviour more difficult. @tbosch I'll be unavailable most of the day, could you review this and see if it's worth landing as an intermediate solution? If not I'll get to it when I'm back home |
29dbe93
to
b28784d
Compare
Fixes absolute links on browsers with html5Mode enabled. Previously clicking on a link out of the base href would still rewrite the URL.
b28784d
to
8dc10a4
Compare
I've updated this PR so that it behaves correctly with base href. I've also added tests. This should now be fully consistent with the URL rewriting logic throughout $location. I don't see how this change will make replacing the broken behavior more difficult since this code change only makes changes to code that was added in e020366 and 24f7999 which are removed on 2294880 anyway. |
256ee55
to
5e5a45f
Compare
Also, just verified that this fixes the docs website on IE9. |
I just read through #8233, I see the concern, I was making the assumption that the base href wouldn't be an absolute URL with protocol. I'm working on a solution that will consider that. All in all, my intention is to fix existing location regressions 1.2.x without requiring base tags as it's a breaking change. |
the docs site was verified to be working with this original fix in IE9, we tested this in SL extensively. The problem is that it breaks many peoples actual apps, in different ways. Basically it doesn't play nicely with a base tag at all, and it never resolved relative URLs correctly (or consistently with the way a history-enabled browser would resolve them). So, requiring a base tag kind of sucks, but there isn't much else we can do to ensure consistent behaviour. It is sad that the base tag and app base are so tied together, but that's the way it is right now. I've asked anne what he'd think about adding some kind of support for multiple base tags (similar to xml:base), but I don't think it was a very popular idea --- it's the kind of thing nobody really wants to support, url resolving in browsers is already ridiculously complicated and it would just make things worse. So unfortunately there's probably no way to do this that makes everyone happy. We can certainly look at it and try it, but I think the most likely scenario is going to be the breaking change, or just reverting the fix entirely and using the default url resolution always |
I'll self-assign this one since @tbosch and I are discussing some changes to |
I just looked through this PR again and found the following cases this PR doesn't handle yet:
For case 2, it might make sense to always urlResolve the base href since if it begins with I have a few questions:
|
It would be nice to have an Unfortunately, this doesn't help us when it comes to resolving URLs correctly. In order to do this consistently, we really need to use URLUtils --- otherwise the difference between the real url and the "virtual" url just completely mess things up. |
How about shimming URLUtils' As long as there's no ambiguity in what the virtual URL is by rewriting the current URL, it shouldn't be too messy. This of course has to take into the account the value of the base href (it's absence means the current url is the base url). Assuming we have that URL function, this is what finding a href looks like: // On load
var documentBaseUri = hasNgBase ? URL(baseHref, initialUrl) : document.baseUri;
function rewrite(href) {
var baseUrl = documentBaseUri || currentUrl;
var newUrl = URL(url, baseUrl);
if (hasBaseTagOrNgBase) {
return inAppBase(newUrl) && newUrl;
} else {
return newUrl;
}
} I looked briefly into Apache's httpcomponents' URIUtils which I'm guessing is one of the more mature implementations of it. It looks like the algorithm we have in e020366 is doing what the |
Just for clarification, this is the behavior I'm assuming right now. Do let me know if my assumptions are incorrect or if I missed some cases. With base href: /base/ (or http://example/base/)The following all navigate to http://example/base/abc Hashbang URLs are always resolved to appBase. It doesn't make sense to have a hashbang href resolves to somewhere out of the application.
With no base hrefEdit: Removed previous examples for case when no base href is set. When no base href is set, the app's base is set to the root. There's no need to handle cases where the base href is pointing to another domain because no URL rewriting should occur in those cases, all relative links should navigate away to external URLs. In that case, only an absolute href to the current app itself can invoke navigation within the app. |
81afe58
to
7a276c3
Compare
I've updated this PR with the URLResolve shim approach. This makes the logic much cleaner and more consistent with the html5 url API. In fact, there's now code shared with LocationHtml5Url to find the absUrl ( The urlResolveShim method is intended to behave like the URLUtils's I saw that the urlUtils.js's urlResolve wasn't respecting the |
I'm done with working on this PR for now, and hope to hear some feedback on it. |
Hi, An Regarding requiring the
Closing this... |
Fixes absolute links on legacy browsers when html5Mode is enabled.
Clicking on a link out of the base's href shouldn't trigger rewriting the URL. This behavior was changed since 24f7999 .
This resolves the issue I found on 24f7999#commitcomment-7815179 which has created different behavior when it comes to absolute links on legacy browsers.
Most of this is whitespace changes.
I've added these cases to consider:
/base/
when the base tag is present with a value of/base/
./
not in within the base (i.e./outer_base/link
)/
/
properly (.i.e.#!/base/thing
).This change is meant to resolve those cases that were not tested since 1.2.17 and have mismatching test cases. It's not to add any new features.