Verwenden von Net :: HTTP.get für eine https-URL

83

Ich versuche, Net::HTTP.get()für eine https-URL zu verwenden:

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

Beim Versuch, die Ergebnisse zu drucken, wird jedoch das folgende Ergebnis angezeigt:

URI :: HTTPS kann nicht in String konvertiert werden

Was ist das Problem? Ich verwende Ruby 1.8.7 (OS X)

Tony Stark
quelle
Nur zu Ihrer Information, wir haben vorübergehend eine Verbindung zu einem Server eines Drittanbieters hergestellt, bei dem Zertifikatsprobleme aufgetreten sind. Daher mussten wir IO.copy_stream( open( url, { ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE } ), download_path )nur die SSL-Überprüfung deaktivieren. In unserem Fall war die Sicherheit kein Problem, der Server war außerhalb unserer Kontrolle und es war eine vorübergehende Lösung.
Joshua Pinter

Antworten:

154

Ursprüngliche Antwort:

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)

Wie in den Kommentaren ausgeführt, ist dies eleganter:

require "open-uri"
@data = URI.parse("https://example.com/some/path").read
stef
quelle
7
Ich werde dies als Antwort geben, weil es die Antwort auf das ist, was ich gefragt habe, aber die wirkliche Antwort ist, darauf hinzuweisen, dass ich dies falsch angehe. Verwenden Sie URI.parse(uri_string).readstattdessen, funktioniert so, so schön.
Tony Stark
2
Was bedeutet VERIFY_NONEdas? Was sollte stattdessen möglicherweise getan werden?
Jonathan Allard
1
Das ist ein Flag, das bedeutet, dass die Richtigkeit des Zertifikats ignoriert wird. Dies ist jedoch eine Weile her, daher bin ich mir nicht sicher, warum Sie es festlegen müssen.
stef
2
@frabcus, müssen Sie, require 'open-uri'damit die .read funktioniert.
Josh D
1
Die Frage des OP weist nicht darauf hin, dass eine SSL-Überprüfung nicht erwünscht ist. Warum schlagen Sie also VERIFY_NONE vor?
Alex
35

EDIT: Mein Ansatz funktioniert, aber der Ansatz von @ jason-yeo ist viel einfacher.

Ab 2.1.2 wird eine dokumentierte Methode wie folgt bevorzugt (direkt unter Angabe der Dokumentation ):

HTTPS wird für eine HTTP-Verbindung durch # use_ssl = aktiviert.

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 früheren Versionen von Ruby mussten Sie 'net / https' benötigen, um HTTPS verwenden zu können. Das stimmt nicht mehr.

eebbesen
quelle
6
Das ist nicht wahr. Ab Ruby 2.0.0 Net::HTTP.getreicht es aus, eine HTTPS- Abrufanforderung auszuführen, wenn dem URI-Objekt eine httpsURL übergeben wird. Siehe meine Antwort: stackoverflow.com/a/36543895/382740 .
Jason Yeo
18

In Ruby 2.0.0 und höher reicht es aus, ein Uri-Objekt mit einer httpsURL zu übergeben, um eine HTTPS-Abrufanforderung auszuführen.

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

Sie können dies überprüfen, indem Sie eine Abrufanforderung für eine Domain mit einem abgelaufenen Zertifikat ausführen .

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

Es wurde durch dieses Commit in Ruby 2.0.0 eingeführt.

Das get_responseVerfahren, das durch das aufgerufen wird , Net::HTTP.getVerfahren, setzt :use_ssl auf wahr , wenn das uri.schemeist „https“.

Haftungsausschluss: Ich verstehe, dass die Frage für Ruby 1.8.7 ist, aber da dies eines der wenigen Suchergebnisse ist, wenn man nach "https ruby" sucht, habe ich mich entschlossen, es trotzdem zu beantworten.

Jason Yeo
quelle
4
Als Datenpunkt habe ich festgestellt, dass dies in Ruby 2.2.10 nicht zutrifft. Die Verbindung an Port 443 wurde zwar geöffnet, es wurde jedoch kein SSL verwendet. Natürlich würde der fremde Server nichts damit zu tun haben und die Verbindung ohne Antwort schließen, was dazu führen würde, dass mir viele Zähne zusammenbeißen. Ich musste anrufen http.use_ssl = true, um es zu zwingen, tatsächlich ssl zu verwenden, und dann lief es schwimmend.
David Hempy
4

das sollte so aussehen:

uri.port = Net::HTTP.https_default_port()
@data = Net::HTTP.get(uri)
Vlad Khomich
quelle
das hat funktioniert, aber jetzt beschwert sich die externe API, dass ich eine einfache HTTP-Anfrage an einen HTTPS-Port gesendet habe ...
Tony Stark
haha, rechts;) siehe unten Lösung Stef zur Verfügung gestellt, sollte es funktionieren
Vlad Khomich
Wenn dies nicht der Fall ist, wird die Fehlermeldung "undefinierte Methode` use_ssl = '"angezeigt
Tony Stark
2
versuchen Sie auch 'net / https' zu verlangen
Vlad Khomich