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"
Tom Lehman
  • 85,973
  • 71
  • 200
  • 272

4 Answers4

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'));
Matt
  • 43,482
  • 6
  • 101
  • 102
  • 1
    '+' is what space encodes to in a query. See the final sentence in [URL encoding](http://en.wikipedia.org/wiki/Query_string#URL_encoding). It's not the same as a space in the parameters for a URL, which would encode as '%20'. – the Tin Man Dec 26 '10 at 21:03
  • 1
    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? – Victor Yarema Nov 21 '16 at 17:51
  • 2
    @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: https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1 – Matt Nov 22 '16 at 01:11
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

user113716
  • 318,772
  • 63
  • 451
  • 440
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"
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
-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.

  • 1
    How does this answer address the question? It is asking about JavaScript and Ruby, not PHP. – Boric Feb 12 '20 at 18:06