web-dev-qa-db-fra.com

Y a-t-il une solution de contournement pour ouvrir des URL contenant des traits de soulignement à Ruby?

J'utilise Open-Uri pour ouvrir des URL.

resp = open("http://sub_domain.domain.com")

S'il contient un soulignement, je reçois une erreur:

 Uri :: InvalidurierRor: le schéma http n'accepte pas la partie de registre: sub_domain.domain.com (ou mauvais nom d'hôte?) [.____]

Je comprends que cela est dû au fait que, selon les URL RFC, ne peut contenir que des lettres et des chiffres. Y a-t-il une solution de contournement?

32
Arty

Cela ressemble à un bogue dans l'Uri et à Uri-Open, httparty et de nombreuses autres gemmes utilisent Uri.Parse.

Voici une solution de contournement:

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")
19
stef

URI a une idée à l'ancienne de ce que ressemble une URL.

Dernièrement, j'utilise addressable pour contourner cela:

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!

N'oubliez pas de gem install addressable

17
pguardiario

Cet initialiseur dans mon Rails App semble faire du travail URI.Parse au moins:

# 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
14
cluesque

Un soulignement ne peut pas être contenu dans un nom de domaine comme celui-là. Cela fait partie de la norme DNS. Voulez-vous vouloir utiliser un tiret (-)?

Même si Open-Uri n'a pas lancé une erreur, une telle commande serait inutile. Pourquoi? Parce qu'il n'y a pas moyen de résoudre un tel nom de domaine. Au mieux que vous obtiendriez un unknown Host Erreur. Il n'y a aucun moyen pour vous d'enregistrer un nom de domaine avec un _ En IT, et même l'exécution de votre propre serveur DNS privé, il est contre la spécification d'utiliser un _. Vous pouvez plier les règles et le permettre (en modifiant le logiciel du serveur DNS), mais que le résolveur DNS du système d'exploitation ne prendra que le support, ni le logiciel DNS de votre routeur.

Solution: n'essayez pas d'utiliser un _ Dans un nom DNS. Ça ne marchera nulle part et il est contre les spécifications

3
Earlz

Voici un correctif qui résout le problème pour une grande variété de situations (client de repos, open-uri, etc.) sans utiliser de gemmes externes ni de pièces primordiales d'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

Source: lib/uri/rfc2396_parser.rb # l86

Ruby-Core a un problème ouvert: https://bugs.ruby-lang.org/issues/8241

3
Larry Kyrala

J'ai eu cette même erreur lors de la tentative d'utilisation de la mise à jour de GEM/GEM, etc., donc j'ai utilisé l'adresse IP à la place et c'est bien maintenant.

2
Julian Mann

Voici un autre piratage laid, aucun gemme nécessaire:

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
2
sheerun

Je recommande d'utiliser le gemme de bordure: https://github.com/taf2/furb qui vient d'envelopper libcurl. Voici un exemple simple qui suivra automatiquement les redirections et imprimera le code de réponse et le corps de réponse:

rsp = Curl::Easy.http_get(url){|curl| curl.follow_location = true; curl.max_redirects=10;}
puts rsp.response_code
puts rsp.body_str

J'évite habituellement les catégories Ruby Cours d'URI car ils sont trop stricks sur la spécification qui, comme vous savez que le Web est le Wild West :) Curl/Curb gère chaque URL que je jette à la fois comme un champion.

0
TomDavies