How to invoke HTTP POST method over SSL in ruby?
You are close, but not quite there. Try something like this instead:
uri = URI.parse("https://auth.api.rackspacecloud.com")http = Net::HTTP.new(uri.host, uri.port)http.use_ssl = truehttp.verify_mode = OpenSSL::SSL::VERIFY_NONErequest = Net::HTTP::Post.new("/v1.1/auth")request.add_field('Content-Type', 'application/json')request.body = {'credentials' => {'username' => 'username', 'key' => 'key'}}.to_jsonresponse = http.request(request)
This will set the Content-Type header as well as post the JSON in the body, rather than in the form data as your code had it. With the sample credentials, it still fails, but I suspect it should work with real data in there.
There's a very good explanation of how to make a JSON POST request with Net::HTTP at this link.
I would recommend using a library like HTTParty. It's well-documented, you can just set up your class like so:
class RackSpaceClient include HTTParty base_uri "https://auth.api.rackspacecloud.com/" format :json headers 'Accept' => 'application/json' #methods to do whateverend
It looks like the main difference between the Ruby code you placed there, and the curl request, is that the curl request is POSTing JSON (content-type application/json) to the endpoint, whereas request.set_form_data
is going to send a form in the body of the POST request (content-type application/x-www-form-urlencoded). You have to make sure the content going both ways is of type application/json.
All others are too long here is a ONE LINER:
Net::HTTP.start('auth.api.rackspacecloud.com', :use_ssl => true).post( '/v1.1/auth', {:credentials => {:username => "username",:key => "key"}}.to_json, initheader={'Content-Type' => 'application/json'} )
* to_json
needs require 'json'
OR if you want to
- NOT verify the hosts
- be more readable
- ensure the connection is closed once you're done
then:
ssl_opts={:use_ssl => true, :verify_mode => OpenSSL::SSL::VERIFY_NONE}Net::HTTP.start('auth.api.rackspacecloud.com', ssl_opts) { |secure_connection| secure_connection.post( '/v1.1/auth', {:credentials => {:username => "username",:key => "key"}}.to_json, initheader={'Content-Type' => 'application/json'} )}
In case it's tough to remember what params go where:
- SSL options are per connection so you specify them while opening the connection.
- You can reuse the connection for multiple REST calls to same base url. Think of thread safety of course.
- Header is a "request header" and hence specified per request. I.e. in calls to
get
/post
/patch
/...
. HTTP.start()
: Creates a new Net::HTTP object, then additionally opens the TCP connection and HTTP session.HTTP.new()
: Creates a new Net::HTTP object without opening a TCP connection or HTTP session.