with tutorial para framework español djangoproject con applications ruby open-uri

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