Search code examples
rubycurlput

Ruby: HTTP Put method


I am attempting to update the 'ip' parameter in a json object in an API.

I have the following case:

when "put"
  uri = URI.parse("http://#{ip}:#{port}/api/v1/address_data/1.json")
  jobj = Hash.new
  jobj['ip'] = "1.1.1.1"
  http = Net::HTTP.new(uri.hostname, uri.port)
  response = http.send_request('PUT', '/api/v1/address_data/1.json', data = jobj.to_s)
end

This does not work, but this does:

curl -X PUT http://ip:port/api/v1/address_data/1.json -d "ip=1.1.1.1"

How do I more accurately translate the curl into a Put request in Ruby? I have tried several methods I've found through google searching, but none of them have had successful results.


Solution

  • A few things:

    • You're not sending JSON in the Ruby example, it's a string representation of a Ruby hash which isn't the same. You need the JSON module or similar.
    • In the Ruby code you're attempting to send a JSON object (which would look like {"ip":"1.1.1.1"} and in the curl example you're sending it in application/x-www-form-urlencoded format, so they're currently not equivalent.
    • Also I'd look at the type of data the server expects from your requests: both Ruby and curl send a request header of Content-Type: application/x-www-form-urlencoded by default, and you're expecting to send JSON. This is why the curl example works: the data format you're using and the header matches. Note the .json in the URL shouldn't really make any difference; the header takes precedence.
    • Your call to send_request has you picking out the data parameter as a Python-style keyword argument. Ruby doesn't do that: what you're actually doing there is assigning a local variable in-line with the call.

    So try something like this:

    require 'json' # put this at the top of the file
    
    uri = URI.parse("http://#{ip}:#{port}/api/v1/address_data/1.json")
    jobj = {"ip" => "1.1.1.1"}
    http = Net::HTTP.new(uri.hostname, uri.port)
    response = http.send_request('PUT', uri.path, JSON.dump(jobj),
      {'Content-Type' => 'application/json'})
    

    And just a friendly reminder, saying something "doesn't work" doesn't usually give enough information to people that might answer your question: try and remember to paste in error messages, stack traces, and things like that :)