tutorial - ¿Existe alguna solución para abrir las URL que contienen guiones bajos en Ruby?
tutorial django (8)
Aquí hay otro hack feo, no se necesitan gemas:
def parse(url = nil)
begin
URI.parse(url)
rescue URI::InvalidURIError
host = url.match(".+/:////([^//]+)")[1]
uri = URI.parse(url.sub(host, ''dummy-host''))
uri.instance_variable_set(''@host'', host)
uri
end
end
Estoy usando open-uri para abrir URLs.
resp = open("http://sub_domain.domain.com")
Si contiene guiones bajos, recibo un error:
URI::InvalidURIError: the scheme http does not accept registry part: sub_domain.domain.com (or bad hostname?)
Entiendo que esto se debe a que, de acuerdo con la RFC, las URL solo pueden contener letras y números. ¿Hay algún trabajo alrededor?
Aquí hay un parche que resuelve el problema para una amplia variedad de situaciones (rest-client, open-uri, etc.) sin usar gemas externas o partes primordiales de URI.parse:
module URI
DEFAULT_PARSER = Parser.new(:HOSTNAME => "(?:(?:[a-zA-Z//d](?:[-//_a-zA-Z//d]*[a-zA-Z//d])?)//.)*(?:[a-zA-Z](?:[-//_a-zA-Z//d]*[a-zA-Z//d])?)//.?")
end
Fuente: lib/uri/rfc2396_parser.rb#L86
Ruby-core tiene un problema abierto: https://bugs.ruby-lang.org/issues/8241
Este inicializador en mi aplicación Rails parece hacer que URI.parse funcione al menos:
# config/initializers/uri_underscore.rb
class URI::Generic
def initialize_with_registry_check(scheme,
userinfo, host, port, registry,
path, opaque,
query,
fragment,
parser = DEFAULT_PARSER,
arg_check = false)
if %w(http https).include?(scheme) && host.nil? && registry =~ /_/
initialize_without_registry_check(scheme, userinfo, registry, port, nil, path, opaque, query, fragment, parser, arg_check)
else
initialize_without_registry_check(scheme, userinfo, host, port, registry, path, opaque, query, fragment, parser, arg_check)
end
end
alias_method_chain :initialize, :registry_check
end
Esto parece un error en URI, y uri-open, HTTParty y muchas otras gemas hacen uso de URI.parse.
Aquí hay una solución:
require ''net/http''
require ''open-uri''
def hopen(url)
begin
open(url)
rescue URI::InvalidURIError
host = url.match(".+/:////([^//]+)")[1]
path = url.partition(host)[2] || "/"
Net::HTTP.get host, path
end
end
resp = hopen("http://dear_raed.blogspot.com/2009_01_01_archive.html")
Recomiendo usar la gema Curb: https://github.com/taf2/curb que simplemente envuelve libcurl. Este es un ejemplo simple que seguirá automáticamente las redirecciones e imprimirá el código de respuesta y el cuerpo de la respuesta:
rsp = Curl::Easy.http_get(url){|curl| curl.follow_location = true; curl.max_redirects=10;}
puts rsp.response_code
puts rsp.body_str
Usualmente evito las clases de URI rubí ya que son demasiado estrictas para la especificación que, como saben, la web es el salvaje oeste :) Curl / frenar maneja cada url que le lanzo como un campeón.
Tuve el mismo error al tratar de usar gem update / gem install etc., así que usé la dirección IP en su lugar y está bien ahora.
Un guión bajo no se puede contener en un nombre de dominio como ese. Eso es parte del estándar DNS. ¿Querías usar un guión ( -
)?
Incluso si open-uri no lanzara un error, tal comando no tendría sentido. ¿Por qué? Porque no hay forma de que pueda resolver ese nombre de dominio. En el mejor de los casos, obtendría un error de unknown host
. No hay forma de que registre un nombre de dominio con un _
en él, e incluso ejecutando su propio servidor DNS privado, está en contra de la especificación usar un _
. Podría doblar las reglas y permitirlo (modificando el software del servidor DNS), pero entonces el sistema de resolución de DNS de su sistema operativo no lo admitirá, como tampoco lo hará el software DNS de su enrutador.
Solución: No intente usar un _
en un nombre DNS. No funcionará en ningún lado y va en contra de las especificaciones
URI
tiene una idea pasada de moda de cómo se ve una url.
Últimamente estoy usando addressable
para evitar eso:
require ''open-uri''
require ''addressable/uri''
class URI::Parser
def split url
a = Addressable::URI::parse url
[a.scheme, a.userinfo, a.host, a.port, nil, a.path, nil, a.query, a.fragment]
end
end
resp = open("http://sub_domain.domain.com") # Yay!
No te olvides de gem install addressable