Usando Net :: HTTP.get para una URL https

84

Estoy tratando de usar Net::HTTP.get()para una URL https:

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

Sin embargo, obtengo el siguiente resultado cuando intento imprimir los resultados:

no se puede convertir URI :: HTTPS en String

¿Cual es el trato? Estoy usando Ruby 1.8.7 (OS X)

Tony Stark
fuente
Solo para su información, nos estábamos conectando a un servidor de terceros temporalmente que tenía problemas de certificado, por lo que tuvimos que usar IO.copy_stream( open( url, { ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE } ), download_path )para deshabilitar la verificación SSL. En nuestro caso, la seguridad no fue un problema, el servidor estaba fuera de nuestro control y fue una solución temporal.
Joshua Pinter

Respuestas:

156

Respuesta original:

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)

Como se señaló en los comentarios, esto es más elegante:

require "open-uri"
@data = URI.parse("https://example.com/some/path").read
stef
fuente
7
Daré esto como respuesta porque es la respuesta a lo que pregunté, pero la respuesta real es señalar que me estoy acercando a esto de la manera incorrecta. Úselo en su URI.parse(uri_string).readlugar, funciona tan, tan maravillosamente.
Tony Stark
2
¿Qué VERIFY_NONEimplica? ¿Qué debería hacerse en su lugar?
Jonathan Allard
1
esa es una bandera que significa que se ignora la veracidad del certificado, pero esto fue hace un tiempo, así que no estoy seguro de por qué necesita configurarlo.
stef
2
@frabcus, necesitas require 'open-uri'para que el .read funcione.
Josh D
1
No hay nada en la pregunta del OP que implique que no se desea la verificación SSL, entonces, ¿por qué sugiere VERIFY_NONE?
Alex
35

EDIT: Mi enfoque funciona, pero @ de Jason-Yeo enfoque es mucho más fácil.

A partir de 2.1.2, el método documentado preferido es el siguiente (citando directamente la documentación ):

HTTPS está habilitado para una conexión HTTP mediante # 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 

En versiones anteriores de Ruby, necesitaría requerir 'net / https' para usar HTTPS. Esto ya no es verdad.

eebbesen
fuente
6
Esto no es verdad. A partir de Ruby 2.0.0, Net::HTTP.getes suficiente realizar una solicitud de obtención HTTPS si se pasa una httpsURL al objeto URI . Vea mi respuesta: stackoverflow.com/a/36543895/382740 .
Jason Yeo
19

En Ruby 2.0.0 y superior, simplemente pasar un objeto uri con una httpsURL es suficiente para realizar una solicitud de obtención HTTPS.

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

Puede verificar esto realizando una solicitud de obtención en un dominio con un certificado caducado.

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

Fue introducido por este compromiso en Ruby 2.0.0.

El get_responsemétodo, que es llamado por el Net::HTTP.getmétodo, se establece :use_ssl en verdadero cuando uri.schemees "https".

Descargo de responsabilidad: Entiendo que la pregunta es para Ruby 1.8.7, pero dado que este es uno de los primeros resultados de búsqueda cuando uno busca "https ruby", he decidido responder de todos modos.

Jason Yeo
fuente
4
Como punto de datos, he descubierto que esto no es cierto en ruby ​​2.2.10. Abrió la conexión en el puerto 443, pero no usó SSL. Por supuesto, el servidor externo no quiso tener nada que ver con eso y cerró la conexión sin una respuesta, lo que provocó que me crujieran los dientes. Tuve que llamar http.use_ssl = truepara forzarlo a usar ssl, y luego las cosas fueron a la perfección.
David Hempy
4

esto debería verse como:

uri.port = Net::HTTP.https_default_port()
@data = Net::HTTP.get(uri)
Vlad Khomich
fuente
eso funcionó, pero ahora la API externa se queja de que envié una solicitud HTTP simple a un puerto HTTPS ...
Tony Stark
haha, derecho;) ver más abajo solución Stef proporcionado, debería funcionar
Vlad Khomich
no lo hace, aparece un error que dice "método indefinido` use_ssl = '"
Tony Stark
2
intente también requerir 'net / https'
Vlad Khomich