Ruby - URL encoding
Asked Answered
T

3

5

I have a URL string where there are line breaks and carriage returns. E.g.

http://xyz.com/hello?name=john&msg=hello\nJohn\n\rgoodmorning&note=last\night I went to \roger

Where my actual msg string is:

hello
john
goodmorning

and note string is

last\night I went to \roger

In order to send it correctly I have to urlencode this

 http://xyz.com/hello?name%3Djohn%26msg%3Dhello%5CnJohn%5Cn%5Crgoodmorning%26note%3Dlast%5Cnight%20I%20went%20to%20%5Croger

But this encode mess up \n and \r. While I expect \n should get converted to %0A and \r to %0D

I am writing code is ruby. And I tried to take help of Addressable::URI but no help yet. Other way could be replacing \n and \r manually to %0A and %0D respectively. But that replacement can replace valid character such as last\night to last%0Aight that I don't want. Can anyone suggest a better solution? Thanks.

Tufthunter answered 4/1, 2013 at 1:47 Comment(0)
V
14

What about CGI::escape

You need to only encode the parameters though.

url = "http://xyz.com/hello?"
params = "name=john&msg=hello\nJohn\n\rgoodmorning&note=last\night I went to \roger"

puts "#{url}#{CGI::escape(params)}"
# => "http://xyz.com/hello?name%3Djohn%26msg%3Dhello%0AJohn%0A%0Dgoodmorning%26note%3Dlast%0Aight+I+went+to+%0Doger"
Veliavelick answered 4/1, 2013 at 2:22 Comment(2)
I was thinking to write monkey patching Class Hash def to_query self.map{|k,v| "#{CGI.escape(k)}=#{CGI.escape(v)}"}.join(“&”) end end so that I can just use hash.to_query but it wont work becaus eof obvious reason "CGI" and throw error NameError: uninitialized constant Hash::CGI is there any way to solve that.Tufthunter
First of all, did not you see that CGI is also escaping the '&'s ? If you want to do something like this, you should also be sure that k and v are strings otherwise CGI::escape will raise an error. And finally, I had no problem testing it locally. You have a weird " in your .join(“&”) and you could try to add :: in front of CGI as ::CGI.Veliavelick
M
3

This is how I'd do it using Addressable::URI:

require 'addressable/uri'

url = 'http://xyz.com/hello'

msg = 'hello
john
goodmorning'

note = "last\night I went to \roger"

uri = Addressable::URI.parse(url)
uri.query_values = {
  'msg'  => msg,
  'note' => note
}

puts uri.to_s

Which returns:

http://xyz.com/hello?msg=hello%0Ajohn%0Agoodmorning&note=last%0Aight%20I%20went%20to%20%0Doger

The \r in \roger and \n in \night are converted because I used a double-quote delimited string, instead of a single-quote delimited string, which would have preserved \r and \n as literals.

Mythical answered 4/1, 2013 at 4:11 Comment(0)
W
1

Passing json, quotes etc in GET request is tricky. In Ruby 2+ we can use Ruby's URI module's 'escape' method.

> URI.escape('http://app.com/method.json?agent={"account":
{"homePage":"http://demo.my.com","name":"Senior Leadership"}}')

But I suggest use it as POST request and pass it as a message body.

Wiebmer answered 18/8, 2017 at 6:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.