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?
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")
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
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
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
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
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.
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
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.