Why doesn't decodeURI("a+b") == "a b"?
Asked Answered
Z

4

24

I'm trying to encode URLs in Ruby and decode them with Javascript. However, the plus character is giving me weird behavior.

In Ruby:

[Dev]> CGI.escape "a b"
=> "a+b"
[Dev]> CGI.unescape "a+b"
=> "a b"

So far so good. But what about Javascript?

>>> encodeURI("a b")
"a%20b"
>>> decodeURI("a+b")
"a+b"

Basically I need a method of encoding / decoding URLs that works the same way in Javascript and Ruby.

Edit: decodeURIComponent is no better:

>>> encodeURIComponent("a b")
"a%20b"
>>> decodeURIComponent("a+b")
"a+b"
Zwolle answered 26/12, 2010 at 20:29 Comment(0)
E
3

You might want to look at URI.encode and URI.decode:

require 'uri'

URI.encode('a + b') # => "a%20+%20b"
URI.decode('a%20+%20b') # => "a + b"

An alternate, that I use a lot, is Addressable::URI:

require 'addressable/uri'
Addressable::URI.encode('a + b') #=> "a%20+%20b"
Addressable::URI.unencode('a%20+%20b') #=> "a + b"
Ekg answered 26/12, 2010 at 20:38 Comment(5)
Ok, nice! Is there any reason to ever use CGI.escape? (Or was it just put there to trick me!)Zwolle
Also, note that URI.encode is deprecated: #2824626Zwolle
@Horace Loeb, then use Addressable::URI.Ekg
URI.(un)escape deprecated? discusses the decision.Ekg
Addressable::URI looks cool, but leaving the standard library is too much overhead. I'll go with URI.encodeZwolle
M
30

+ is not considered a space. One workaround is to replace + with %20 and then call decodeURIComponent

Taken from php.js' urldecode:

decodeURIComponent((str+'').replace(/\+/g, '%20'));
Munificent answered 26/12, 2010 at 20:36 Comment(3)
'+' is what space encodes to in a query. See the final sentence in URL encoding. It's not the same as a space in the parameters for a URL, which would encode as '%20'.Ekg
Thanks. Your decoding works fine. There is still one question left. Could you please explain WHY the plus sign is not considered as a space?Ourself
@VictorYarema I can't tell you how it came to be that way. But the issue is query strings are considered application/x-www-form-urlencoded - not URIs. And that MIME has a rule that says spaces must be encoded as +. Relevant section: w3.org/TR/html401/interact/forms.html#h-17.13.4.1Munificent
B
4

From MDC decodeURI:

Does not decode escape sequences that could not have been introduced by encodeURI.

From MDC encodeURI:

Note that encodeURI by itself cannot form proper HTTP GET and POST requests, such as for XMLHTTPRequests, because "&", "+", and "=" are not encoded

Billon answered 26/12, 2010 at 20:35 Comment(0)
E
3

You might want to look at URI.encode and URI.decode:

require 'uri'

URI.encode('a + b') # => "a%20+%20b"
URI.decode('a%20+%20b') # => "a + b"

An alternate, that I use a lot, is Addressable::URI:

require 'addressable/uri'
Addressable::URI.encode('a + b') #=> "a%20+%20b"
Addressable::URI.unencode('a%20+%20b') #=> "a + b"
Ekg answered 26/12, 2010 at 20:38 Comment(5)
Ok, nice! Is there any reason to ever use CGI.escape? (Or was it just put there to trick me!)Zwolle
Also, note that URI.encode is deprecated: #2824626Zwolle
@Horace Loeb, then use Addressable::URI.Ekg
URI.(un)escape deprecated? discusses the decision.Ekg
Addressable::URI looks cool, but leaving the standard library is too much overhead. I'll go with URI.encodeZwolle
R
-1

You also get the same problem of a+b when sending a response from php via XMLHttpRequest if you use php urlencode. To solve it you have to use the php rawurlencode function.

From XMLHttpRequest to php urldecode works fine for some reason.

Rubie answered 12/2, 2020 at 17:50 Comment(1)
How does this answer address the question? It is asking about JavaScript and Ruby, not PHP.Cutlerr

© 2022 - 2024 — McMap. All rights reserved.