New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
try to more consistently handle URI-encoded URLs #108
Conversation
Wow this is such a timely patch, I was just trying to figure out why my URls were getting messed up with Chinese characters. Thank you thank you thank you! |
I'll have a better patch later today. This one doesn't handle some edge cases properly with encoded URI separators (&, #, ;, etc.). Also, I make no guarantees about whether or not this works in the older browsers for which history.js maintains compatibility. My testing setup is somewhat limited. |
This is much better than what I had in #107, but there are still a few little bugs:
We're using the master branch on our site, so I can't add directly to this pull request. Instead I've updated #107 to match this request, plus an extra commit with the issues discussed above. Hopefully you can cherry-pick that last commit to get the fixes. |
Ah, I forgot - I also spotted an extra "fragement" typo - fixed in commit 9234ea7, not in the last commit. |
Try commit 31eb079 and see if that fixes your issues with FF3.6. document.URL does actually include the hash in FF3.6 (got to be careful with that), but document.URL does not update as document.location.hash changes. I pulled in your fragment changes, but didn't pull in the other changes you identified (I left some comments highlighting what I think may be some problems with them). |
hrunting's changes definitely worked for me. I recommend merging them in. |
I seem to be running into an issue with IE9 (HTML4 browsers) that I think is related to this code. On these browsers the statechange event doesn't fire after pushState() when there are special characters which are already URL encoded in the URL passed to pushState(). The behavior is:
The problem is in Step 4. When it compares the new hash to the old one (newStateHash !== html4Hash), the newStateHash is URL-decoded but the html4Hash has the %-encoded characters. i.e. '?t=@' !== '?t=%40'. When constructing a URL that is a query string I do think I need to call encodeURIComponent() on each key and value just in case there are special characters like =, ?, or & in there. Anyone else seen this? Maybe it's something I messed up on my end when I copied this code over? |
If I change the initialization of html4Hash as:
This seems to fix my issue ... at least for my limited test case. Not totally comfortable I've hit on the core issue here, though. |
I have the same problem as @dobesv in IE8 and IE9 This is what i get with @hrunting's code:
When I add
I also tried
Further help with this would be greatly appreciated. By the way: Many thanks to @hrunting and @andrew-sayers--slando. their changes definitely work very well for me in FF an Chrome. |
Hmm interesting it appears that in your case the newStateHash has been double-encoded (%-encoded and then % itself further replaced with %25) and yet your html4Hash is just normally %-encoded. How are you passing the URL into pushState()? |
Basically this is the URL that is pushed:
|
I think there probably is an edge case with query arguments and HTML4 browsers. I'll need to spend some time going through some of the edge cases presented above. I think the "?@" is reasonably simple enough to test. When you pass the result of I'll see what I can put together. Thanks for the test cases. |
Try that commit and see if it works for you. I haven't fully tested it yet, but it solved the condition with dobesv's test case. |
Thanks a million @hrunting for coming back to this issue and trying to find a solution! I pulled your commit but unfortunately it's still not working. The problem is still that the hashes never become equal, so we get an infinite loop of After that I looked a little more closely at the So there must be more going on than a simple encoding problem. Unfortunately I haven't quite understood the whole workflow yet. Please let me know if I can provide any more information to solve this issue. How would I go about creating a "real" testcase that you could work with? Also, to the question about the encoding of what I push into pushState in the first place: I do believe that jQuery's serialize() will encode all the components using encodeURIComponent. So that should be fine? Or should I try something different there? Again, thanks a million and I hope this can get solved somehow. |
jhilden, can you post the original initial call to pushState and the value that you're passing? It's weird that your newStateHash is getting double-encoded. I want to create a test case like I did with dobesv's example to look at it more closely. The problem that I was looking at was pretty simple. When the State instance is initialized, the hash gets unescaped. In dobesv's case, that meant that "?%40" got translated internally to "?@". There's nothing wrong with that -- they're both equivalent URLs -- but it means you can't rely on straight-up string comparisons, and that's what isEqualHash() does -- reduces all the encoding ambiguity (I'd rather the history code be more consistent about encoding, but I'm not totally up to speed on all of that). In your case, the two really aren't equivalent at all. Something like "?utf8=%25E2%259C%2593" is not equivalent to "?utf8=%E2%9C%93". But I can't reproduce that. In my test, when I pass in the first, I never end up at the latter. |
@hrunting this is the URL that gets pushed:
|
So you're pushing the full URL (proto + host + path + query) or are you pushing |
Yes, I'm pushing the full URL. |
jhilden, I'm sorry, but I simply can't reproduce the problem you're seeing. I've tried every which way. It always works just fine in IE9. Does your IE happen to be running in quirks mode because of your page doesn't declare a DOCTYPE or something like that? If you could send me the full HTML and JS for the system that's causing the problem, I could probably debug it, but in my simple cases, reproducing your URL as is, IE9 isn't having any problems. |
@hrunting thank you again for looking at my problem. I guess it's not really possible to give you all the HTML and JS, but maybe you could give me what you were experimenting with, so I can play with it on my setup? |
https://gist.github.com/1801624 Here's a basic page I've been using for testing. Put the URL you want to test in the go() call at line 51. I tested with all manner of variations that you posted and haven't been able to reproduce the endless loop you're seeing, so if you can reproduce the endless loop with this test page, let me know the go() call you made. |
Let me ask a question on URL (de)encoding here. But current browser URL has been changed to "/index[ObjectList:surveys]" - i.e. unencoded. |
Did you do this with the patch attached to this thread, or a plain copy of On Thu, Mar 15, 2012 at 6:26 AM, evil-shrike <
|
with plain copy (1.7.1-r2) |
Ah, I see. Well if you download the patched version it might fix your On Thu, Mar 15, 2012 at 5:36 PM, evil-shrike <
|
We're seeing a problem with the encoding of the value of the Is anything like this pull request likely to be accepted and merged in the near future? |
across different browsers (e.g. Safari 5.1)
and make sure that every character is encoded like document.URL
extended to better handle some edge cases in IE and Safari