Making http Post and Get requests in Ruby on Rails

Because everything now has and should have an API, one of the most common things you have to learn and use in any language is how to make API calls. Usually this is done via http using REST, SOAP, or XML. I prefer using RESTFul APIs because they are actually a lot easier to use. I already did a post on PHP cURL for php Ninjas.

Basically http protocol specifies 4 methods to retrieving and updating data to a remote server and the include;

HTTP method function
GET Read
PUT Update/Replace
PATCH Update/Modify
DELETE Delete

To make http requests you have to use the Net::HTTP library. You include it in your code by simply adding require 'net/http' either in your Gemfile or where you need to use it.

Making Get request

Get requests are one of the most common requests you will make on a remote server. It simply retrieves a specific resource.

By the way, the best way to learn a library is to use the interactive ruby console. You can test your code, learn about the different methods it has before etc. There are two; irb which comes pre-installed with ruby or pry which I prefer.

The first step to making an http request is specifying the url endpoint. URL has three components; the hostname, the port number and the url path.

pry(main)> require 'net/http'  
=> true
[15] pry(main)> uri = URI("http://pizzaguru.com/order/") 
=> #<URI::HTTP http://pizzaguru.com/order/>
[16] pry(main)> uri.host
=> "pizzaguru.com"
[17] pry(main)> uri.port
=> 80
[18] pry(main)> uri.path
=> "/order/"

Now we can create the http object, then create our request and then pass the request to the http object like so;

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

You can try it in the interactive console and see results before you commit to adding it to your code;

[19] pry(main)> http = Net::HTTP.new(uri.host, uri.port)
=> #<Net::HTTP pizzaguru.com:80 open=false>
[20] pry(main)> req = Net::HTTP::Get.new(uri.path)
=> #<Net::HTTP::Get GET>
[21] pry(main)> resp = http.request(req)
=> #<Net::HTTPNotFound 404 Not Found readbody=true>
[22] pry(main)> resp.body
=> "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n<title>404 Not Found</title>\n</head><body>\n<h1>Not Found</h1>\n<p>The requested URL /order/ was not found on this server.</p>\n<p>Additionally, a 404 Not Found\nerror was encountered while trying to use an ErrorDocument to handle the request.</p>\n<hr>\n<address>Apache Server at pizzaguru.com Port 80</address>\n</body></html>\n"
[23] pry(main)> resp.code
=> "404"

So you can see, I get error 404 because I just made up pizzaguru.com...oh just realized that the site actually exists!!! Good for them.

Making Post request

The other thing you will most likely want to do is make post requests to a remote web service. You can send post data either as xml, form data (which is common with web forms) or json data. It's increasingly common for APIs to accept json post data because of the simple and structural nature of json.

In case you want to send form data, then you can use the setformdata() method which accepts a hash like

req.set_form_data({"pizza_type" => "Margherita", "pizza_no" => "2"})  

But if you want to post json data, then all you have to do is set the request body and then convert your ruby hash to json. So you need the json library of course. The other to consider is adding our request headers to our http object which specify which type of data we are sending to the server -- in this case json. Also most APIs, require some sort of authorization, which is actually required in your headers. Your code will look something like this;

def make_post_req  
    require 'net/http'
    require 'json'
    begin
        uri = URI('http://pizzaguru.com/place_order')
        http = Net::HTTP.new(uri.host, uri.port)
        req = Net::HTTP::Post.new(uri.path, {'Content-Type' =>'application/json',  
          'Authorization' => 'XXXXXXXXXXXXXXXX'})
        req.body = {"pizza_type" => "Margherita", "pizza_no" => "2"}.to_json
        res = http.request(req)
        puts "response #{res.body}"
        puts JSON.parse(res.body)
    rescue => e
        puts "failed #{e}"
    end
  end

Further reading
- https://ruby-doc.org/stdlib-2.4.1/libdoc/net/http/rdoc/Net/HTTP.html
- http://www.rubyinside.com/nethttp-cheat-sheet-2940.html

David Okwii

David Okwii is a Systems Engineer who currently works with Uganda's country code top-level domain registry.

Kampala Uganda http://www.davidokwii.com

Subscribe to oquidave@geek:~ #

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!