Question

The following code fails to execute:

require 'net/http'

uri = URI('https://example.com:8443')
http = Net::HTTP.new(uri.host, uri.port)

# Enable SSL/TLS ?
if uri.scheme == "https"
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_PEER
  http.ca_file = File.join(File.dirname(__FILE__), "ca-rsa-cert.pem")
end

http.start {
  http.request(uri)
}

The error is:

$ ./TestCert.rb
/usr/lib/ruby/1.9.1/net/http.rb:1292:in `request': undefined method `set_body_internal'
for #<URI::HTTPS:0x00000001a47fd0 URL:https://example.com:8443> (NoMethodError)
    from ./TestCert.rb:16:in `block in <main>'
    from /usr/lib/ruby/1.9.1/net/http.rb:745:in `start'
    from ./TestCert.rb:15:in `<main>'

Unlike Ruby NoMethodError (undefined method `set_body_internal') with HTTP get, I'm using HTTPS and I don't care about a response. I simply need Ruby to make the connection to test the SSL/TLS server.

I did try to capture a response per the related question, but that had the same error:

http.start {
  response = http.request uri
}

And this had the same error:

response = http.start {
  http.request uri
}

And http.get failed too (but with a different error - undefined method 'empty?'):

response = http.start {
  http.get uri
}

And another failure (but with a different error - undefined method 'empty?'):

http.start {
  response = http.get uri
}

If it matters, this is a Debian 7.3 (x64) system running Ruby 1.9.3p194.

How do I make a HTTP request over SSL/TLS using Ruby?

Was it helpful?

Solution

I think your call http.request(uri) is wrong, you should pass a kind of request object like Net::HTTP::Get instead of the uri. Try with the following code:

require 'net/http'

uri = URI('https://example.com:8443')
http = Net::HTTP.new(uri.host, uri.port)

# Enable SSL/TLS ?
if uri.scheme == "https"
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_PEER
  http.ca_file = File.join(File.dirname(__FILE__), "ca-rsa-cert.pem")
end

req = Net::HTTP::Get.new('/')
http.request(req)

Or call directly request_get('/'). That method will create the Get object for you, like the documentation explain:

def request_get(path, initheader = nil, &block) # :yield: +response+
  request(Get.new(path, initheader), &block)
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top