47

How do I make an HTTP GET request with parameters in Ruby?

It's easy to do when you're POSTing:

  require 'net/http'
  require 'uri'

  HTTP.post_form URI.parse('http://www.example.com/search.cgi'),
                 { "q" => "ruby", "max" => "50" }

But I see no way of passing GET parameters as a hash using 'net/http'.

Alex Dean
  • 15,575
  • 13
  • 63
  • 74
Tom Lehman
  • 85,973
  • 71
  • 200
  • 272

7 Answers7

87

Since version 1.9.2 (I think) you can actually pass the parameters as a hash to the URI::encode_www_form method like this:

require 'uri'

uri = URI.parse('http://www.example.com/search.cgi')
params = { :q => "ruby", :max => "50" }

# Add params to URI
uri.query = URI.encode_www_form( params )

and then fetch the result, depending on your preference

require 'open-uri'

puts uri.open.read

or

require 'net/http'

puts Net::HTTP.get(uri)
lime
  • 6,901
  • 4
  • 39
  • 50
  • remove the comma :D uri = URI.parse('http://www.example.com/search.cgi') – Ioane Sharvadze Nov 24 '16 at 17:17
  • 2
    Note that `URI.encode_www_form(foo: "bar,baz")` produces `foo=bar&foo=baz`. If that's not what you expect, I recommend the accepted answer that uses `CGI.escape` or better yet something more full-featured like the RestClient gem. – Leo Oct 05 '18 at 19:42
32

Use the following method:

require 'net/http'
require 'cgi'

def http_get(domain,path,params)
    return Net::HTTP.get(domain, "#{path}?".concat(params.collect { |k,v| "#{k}=#{CGI::escape(v.to_s)}" }.join('&'))) if not params.nil?
    return Net::HTTP.get(domain, path)
end

params = {:q => "ruby", :max => 50}
print http_get("www.example.com", "/search.cgi", params)
Marc-André Lafortune
  • 78,216
  • 16
  • 166
  • 166
Chris Moos
  • 691
  • 6
  • 7
  • 12
    Surely there must be a more abstract way to do this, no? – Tom Lehman Aug 09 '09 at 21:56
  • I don't think there is in Net::HTTP...but you could just write a method that takes 3 parameters, the domain, path, and parameters, and returns the result, so you don't have to run the collect manually each time. – Chris Moos Aug 09 '09 at 22:01
  • @Horace Loeb There is no point abstracting this. It's so simple an abstraction isn't going to save you any code. – Henry Aug 09 '09 at 22:43
  • 1
    What's the point of the `reverse` here? Given that hashes are orderless (usually), and the order of the variables on the query doesn't matter. – Alex Wayne Jul 19 '10 at 16:20
  • 4
    Instead of using `if not` use `unless` –  Feb 01 '11 at 12:50
21
require 'net/http' require 'uri'

uri = URI.parse( "http://www.google.de/search" ); params = {'q'=>'cheese'}

http = Net::HTTP.new(uri.host, uri.port) 
request = Net::HTTP::Get.new(uri.path) 
request.set_form_data( params )

# instantiate a new Request object
request = Net::HTTP::Get.new( uri.path+ '?' + request.body ) 

response = http.request(request)
puts response.body

I would expect it to work without the second instantiation as it would be the first request-objects or the http-object's job but it worked for me this way.

marc
  • 211
  • 1
  • 3
  • 3
    if you do `URI.parse( "http://www.google.de/search?q=cheese" )`, skip the badly named set_form_data, using `..::GET.new(uri.to_s)` that worked for me, without the hopeless second `new` instantiation. The net/http lib changeover is long overdue! – oma Jan 28 '11 at 13:09
7
Net::HTTP.get_print 'localhost', '/cgi-bin/badstore.cgi?searchquery=crystal&action=search&x=11&y=15'

or

uri = URI.parse("http://localhost")
req = Net::HTTP::Get.new("/cgi-bin/badstore.cgi?searchquery=crystal&action=search&x=11&y=15")

http = Net::HTTP.new(uri.host, uri.port)

response = http.start do |http| 
  http.request(req)
end
perimosocordiae
  • 17,287
  • 14
  • 60
  • 76
mike
  • 71
  • 1
  • 1
4

Use Excon:

conn = Excon.new('http://www.example.com/search.cgi')
conn.get(:query => { "q" => "ruby", "max" => "50" })
Alex Dean
  • 15,575
  • 13
  • 63
  • 74
2

new to stack overflow and I guess I can't comment, but @chris.moose is missing double quotes in his function def. line 5 should be:

return Net::HTTP.get(domain, "#{path}?".concat(params.collect { |k,v| "#{k}=#{CGI::escape(v.to_s)}" }.reverse.join('&'))) if not params.nil?

or here's the whole thing redefined for copy/pasting

require 'net/http'
require 'cgi'

def http_get(domain,path,params)
    return Net::HTTP.get(domain, "#{path}?".concat(params.collect { |k,v| "#{k}=#{CGI::escape(v.to_s)}" }.reverse.join('&'))) if not params.nil?
    return Net::HTTP.get(domain, path)
end

<3 -mike

Michael Glass
  • 1,011
  • 8
  • 6
0
This is the easiest way to do it

 require 'net/http' require 'uri'
 @siteurl = "http://www.google.de/search/#{@yourquery}"
define your query
 @yourquery = "whatever"



uri = URI.parse( "@siteurl" );
http = Net::HTTP.new(uri.host, uri.port) 
request = Net::HTTP::Get.new(uri.path) 

# instantiate a new Request object
request = Net::HTTP::Get.new( uri.path+ '?' + request.body ) 

response = http.request(request)
puts response.body

Might not be perfect but at least you get the idea.

user2903934
  • 59
  • 1
  • 11