92

I'm trying to use Net::HTTP.get() for an https URL:

@data = Net::HTTP.get(uri, Net::HTTP.https_default_port())

However, I get the following result when I try to print the results:

can't convert URI::HTTPS into String

What's the deal? I'm using Ruby 1.8.7 (OS X)

eebbesen
  • 5,070
  • 8
  • 48
  • 70
Tony Stark
  • 24,588
  • 41
  • 96
  • 113
  • Just an FYI, we were connecting to a 3rd party server temporarily that had certificate issues so we had to use `IO.copy_stream( open( url, { ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE } ), download_path )` to just disable the SSL verification. In our case, security wasn't an issue, the server was out of our control and it was a temporary solution. – Joshua Pinter Jun 04 '20 at 17:31

4 Answers4

164

Original answer:

uri = URI.parse("https://example.com/some/path")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
@data = http.get(uri.request_uri)

As pointed out in the comments, this is more elegant:

require "open-uri"
@data = URI.parse("https://example.com/some/path").read
mb21
  • 34,845
  • 8
  • 116
  • 142
stef
  • 14,172
  • 2
  • 48
  • 70
  • 7
    I'll give this as the answer because it's the answer to what I asked, but the real answer is to point out i'm approaching this the wrong way. Use `URI.parse(uri_string).read` instead, works so, so beautifully. – Tony Stark Apr 26 '11 at 07:18
  • hatorade, I can't get that with ".read" to work for me at all. could you post a full answer to your own question with how you do this? – frabcus Sep 30 '11 at 10:48
  • 2
    What does `VERIFY_NONE` imply? What should possibly be done instead? – Jonathan Allard Dec 30 '11 at 22:58
  • 1
    that's a flag that means the veracity of the certificate is ignored, but this was a while ago so I'm not sure why you need to set it. – stef Jan 02 '12 at 09:02
  • shouldn't it be @data = http.get uri.request_uri ?? – djfm Jul 17 '12 at 18:46
  • 3
    @frabcus, you need to `require 'open-uri'` for the .read to work. – Lifeweaver Jul 29 '13 at 12:04
  • Not working for me on Ruby 2.0. Any tips? I get "TypeError: no implicit conversion of Pathname into String" – elsurudo Sep 24 '13 at 21:49
  • 1
    There's nothing in the OP's question to imply that SSL verification isn't desired, so why are you suggesting VERIFY_NONE? – Alex Jul 28 '16 at 00:42
  • 2
    Do note that setting `http.verify_mode = OpenSSL::SSL::VERIFY_NONE` will disable certificate verification. An attacker might be able to pretend to be the server you are connecting. In other words, apart from encryption, you are not getting much benefit from SSL at all. – Jason Yeo Aug 11 '16 at 06:56
  • This approach doesn’t seem to capture the body with error message in the case of status code 400s. – Dave Briccetti Sep 12 '19 at 06:40
38

EDIT: My approach works, but @jason-yeo's approach is far easier.

It appears as of 2.1.2 the preferred a documented method is as follows (directly quoting the documentation):

HTTPS is enabled for an HTTP connection by #use_ssl=.

uri = URI('https://secure.example.com/some_path?query=string')

Net::HTTP.start(uri.host, uri.port,   
  :use_ssl => uri.scheme == 'https') do |http|
  request = Net::HTTP::Get.new uri

  response = http.request request # Net::HTTPResponse object 
end 

In previous versions of Ruby you would need to require ‘net/https’ to use HTTPS. This is no longer true.

Community
  • 1
  • 1
eebbesen
  • 5,070
  • 8
  • 48
  • 70
  • 7
    This is not true. As of Ruby 2.0.0, `Net::HTTP.get` is sufficient to do a HTTPS get request if the URI object is passed a `https` url. See my answer: http://stackoverflow.com/a/36543895/382740. – Jason Yeo Apr 11 '16 at 08:50
28

In Ruby 2.0.0 and above, simply passing in an uri object with a https url is sufficient to do a HTTPS get request.

uri = URI('https://encrypted.google.com')
Net::HTTP.get(uri)

You may verify this by performing a get request on a domain with an expired certificate.

uri = URI('https://expired.badssl.com/')
Net::HTTP.get(uri)
# OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed

It was introduced by this commit in Ruby 2.0.0.

The get_response method, which is called by the Net::HTTP.get method, sets :use_ssl to true when the uri.scheme is "https".

Disclaimer: I understand that the question is for Ruby 1.8.7, but since this is one of the top few search results when one searches for "https ruby", I've decided to answer anyway.

Jason Yeo
  • 3,602
  • 3
  • 30
  • 38
  • 8
    As a data point, I have found this to not be true in ruby 2.2.10 . It did open the connection on port 443, but did not use SSL. Of course, the foreign server would have nothing to do with it, and closed the connection without a reply, leading to much teeth gnashing on my end. I had to call `http.use_ssl = true` to force it to actually use ssl, and then things went swimmingly. – David Hempy Apr 24 '18 at 18:59
4

this should look as:

uri.port = Net::HTTP.https_default_port()
@data = Net::HTTP.get(uri)
Vlad Khomich
  • 5,820
  • 1
  • 27
  • 39