-
Notifications
You must be signed in to change notification settings - Fork 27.4k
$location does not parse query portion of URL correctly when in non-html5 mode. #15856
Comments
Note that according to RFC 3986, the fragment can contain |
I disagree pretty strongly with this understanding of the RFC and in particular point to the code itself to show why. While it's true that the RFC allows the ? character in the fragment portion of the URL and gives wide latitude in the semantics of the contents of the fragment, the RFC also makes clear that the contents of the fragment are not the URI And that URI semantics don't apply to fragment contents. However, the query portion of a URL is well-defined, and has a well-defined location in the context of the overall URI-- specifically NOT in the fragment. Your design effectively overwrites the semantics of a URL from something well-defined (both in terms of the spec and in terms of browser behaviour) to something arbitrary and in conflict with the RFC and browser behaviour. Your code itself makes this clear in the function Fundamentally, the AngularJS code misunderstands the original URL because it falsely construes the base url portion to include the non-fragment query portion of the URL instead of including the query portion in the parsed app url. Perhaps a change here that you would accept is to copy the non-fragment query portion of the URL into the faux query portion left behind in the parsed app url? so in that scenario a URL like
would become an app url of
? |
I disagree with you disagreeing 😁 This is not about the understanding of the RFC. This is about implementing client-side routing and deep-linking for Single Page Applications (something that is well outside the scope of the RFC). In order to enable these features, we need to embed the part that represents the client-side path/routing state into the actual URL. There are two alternatives:
HTML5 mode Pros:
HTML5 mode Cons:
Hahbang mode Pros:
Hashbang mode Cons:
It is important that the server-side and client-side parts of the URL are kept separated (and copying the actualy query into the fragment would break that). Hashbang mode is one fo the alternatives, it is optional (so don't have to use it if it is not suitable for your usecase) and does not contradict with any RFC. (This is just my undertanding and I respect that there can be deferring opinions. That's a good thing. Not everyone has to agree on everything 😁) |
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 angular#15856
I don't want to continue to argue about this much longer, but I do want you to consider that if I were to offer up a PR that includes karma tests, that you would seriously consider merging it into angular. While obviously the benefit of OSS is that we can maintain our own fork, that can end up being a big pain. Also I'm sure you've been developing software for far longer than I have, and I appreciate you taking the time to respond to my posts here. But the truth is that I think that there is some misunderstanding of what these URLs and RFC and client side routing is all about. Let's take a step back for a second. A URL locates a resource, and that location can point to a lot of different places. Sometimes it's a file:// URL, sometimes it's an http:// URL, sometimes even esoteric or defunct protocols can be specified in the scheme, like gopher://. And I'm starting with the scheme to point out that you might be mistaken when you say things like
because the idea of a "server-side" or "client-side" of the URL is probably a misunderstanding of what a URL is and what the RFC says. For example, the RFC talks mostly about "user agents" when it comes to parsing URLs. It's up to the user agent to parse the URL and to do something with it. In the case of a file:// URL, there isn't any server involved and as a matter of fact the bug that I'm facing has to do with file:// URLs. Particularly, let me ask you this: what do you think the semantics should be for a URL that uses a proxy pattern to modify just the scheme part of a url from http:// to file:// and then back again? And have you considered the possibility that the same url should work correctly no matter whether or not it's used in a user agent that follows the html5 history API (html5 mode) or a user agent that relies on the non-html5 hashbang mode? Because right now from what I can tell, the same URL would have different semantics in the $location service depending on the mode of the user agent, and that strikes me as another way to describe this issue. In my case, if angularjs's $location service doesn't understand the actual query portion of the URL to also be the query portion of the parsed $location in the non-html5 mode but it does understand the query portion of the URL to be part of the parsed $location when it's in html5 mode, that should be considered as a bug. My approach to copy the query portion of the URL into the fragment of the URL only in the non-html5 hashbang mode should be backwards compatible because apps should ignore query parameters for which they aren't specifically looking. I've updated my branch to includes karma tests for this change and ensured that the solution handles all existing test cases. I would ask you to consider accepting this change to fix the underlying issue that the semantics of a URL in html5 mode vs non-html5 mode is different in angular. URLs should mean the same to the application regardless of the modes available in the user agent. Thanks, |
I'm submitting a ...
Current behavior:
When the $locationProvider has set html5 mode to false, URLs that follow the RFC for URIs (RFC 3986) and include both a query string portion and a fragment portion in the URI will not have the query string portion set, so
$location.search('foo')
is empty. In fact even the documentation for$location
is wrong, since it gives an example like this:// given URL http://example.com/#/some/path?foo=bar&baz=xoxo
even though the RFC is perfectly clear that a well formed URL looks like this:
URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
(see https://tools.ietf.org/html/rfc3986#appendix-A).Expected / new behavior:
AngularJS should respect the specification and work properly when the query portion of the URL appears before the fragment portion.
Minimal reproduction of the problem with instructions:
Reproducing the problem is simple on any browser that follows the specification. Attempt to navigate to a URL such as
http://example.com/foo?query=bar&baz=topaz#/path/to/angular/route
and you'll find that the $location service does not know about the query parameters in this URL.Angular version: 1.x.y
I have noticed this problem in 1.5.7 but the same patch applies cleanly to master as of this writing so I assume the problem continues to exist in master as of this issue report.
Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ]
iOS WKWebView
Anything else:
I have a PR ready to go for this.
The text was updated successfully, but these errors were encountered: