Использование Net :: HTTP.get для URL-адреса https

84

Я пытаюсь использовать Net::HTTP.get()для https URL:

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

Однако при попытке распечатать результаты получаю следующий результат:

не может преобразовать URI :: HTTPS в строку

В чем дело? Я использую Ruby 1.8.7 (OS X)

Тони Старк
источник
Просто к вашему сведению, мы временно подключались к стороннему серверу, у которого были проблемы с сертификатом, поэтому нам пришлось IO.copy_stream( open( url, { ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE } ), download_path )просто отключить проверку SSL. В нашем случае безопасность не была проблемой, сервер был вне нашего контроля, и это было временным решением.
Джошуа Пинтер

Ответы:

156

Оригинальный ответ:

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)

Как указано в комментариях, это более элегантно:

require "open-uri"
@data = URI.parse("https://example.com/some/path").read
Стеф
источник
7
Я дам это как ответ, потому что это ответ на то, что я спросил, но настоящий ответ - указать, что я подхожу к этому неверно. Используйте URI.parse(uri_string).readвместо этого, так красиво работает.
Тони Старк
2
Что VERIFY_NONEзначит? Что, возможно, следует сделать вместо этого?
Джонатан Аллард,
1
это флаг, который означает, что достоверность сертификата игнорируется, но это было давно, поэтому я не уверен, зачем вам его устанавливать.
stef 02
2
@frabcus, вам нужно, чтобы require 'open-uri'.read работал.
Josh D
1
В вопросе OP нет ничего, что могло бы означать, что проверка SSL не требуется, так почему вы предлагаете VERIFY_NONE?
Alex
35

EDIT: Мой подход работает, но @ JASON-Ео в подходе гораздо проще.

Похоже, что начиная с версии 2.1.2 предпочтительный документированный метод выглядит следующим образом (с прямым цитированием документации ):

HTTPS включен для HTTP-соединения с помощью # 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 

В предыдущих версиях Ruby для использования HTTPS требовалось указать net / https. Это уже не так.

Eebbesen
источник
7
Это неправда. Начиная с Ruby 2.0.0, Net::HTTP.getдостаточно выполнить запрос на получение HTTPS, если объекту URI передается httpsURL-адрес. См. Мой ответ: stackoverflow.com/a/36543895/382740 .
Джейсон Йео
19

В Ruby 2.0.0 и выше простой передачи объекта uri с httpsURL-адресом достаточно для выполнения запроса на получение HTTPS.

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

Вы можете проверить это, выполнив запрос на получение в домене с просроченным сертификатом.

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

Он был введен этим коммитом в Ruby 2.0.0.

get_responseМетод, который вызывается Net::HTTP.getметод, устанавливает :use_ssl , чтобы верно , когда uri.schemeэто «HTTPS».

Отказ от ответственности: я понимаю, что вопрос касается Ruby 1.8.7, но поскольку это один из немногих лучших результатов поиска по запросу «https ruby», я все равно решил ответить.

Джейсон Йео
источник
5
Что касается данных, я обнаружил, что это неверно в ruby ​​2.2.10. Он действительно открыл соединение на порту 443, но не использовал SSL. Конечно, чужой сервер не имел к этому никакого отношения и закрыл соединение без ответа, что привело к сильному скрежету зубов с моей стороны. Мне пришлось позвонить, http.use_ssl = trueчтобы заставить его использовать ssl, но потом все пошло гладко.
Дэвид Хемпи
4

это должно выглядеть так:

uri.port = Net::HTTP.https_default_port()
@data = Net::HTTP.get(uri)
Влад Хомич
источник
это сработало, но теперь внешний API жалуется, что я отправил простой HTTP-запрос на HTTPS-порт ...
Тони Старк
хаха, правильно;) см. ниже решение, которое предоставил Стеф, оно должно работать
Влад Хомич
это не так, я получаю сообщение об ошибке "undefined method` use_ssl = '"
Тони Старк,
2
попробуйте также требовать net / https
Влад Хомич