在Ruby中打开包含下划线的URL有解决方法吗?
我正在使用openuri来打开url在Ruby中打开包含下划线的URL有解决方法吗?,ruby,open-uri,Ruby,Open Uri,我正在使用openuri来打开url resp = open("http://sub_domain.domain.com") 如果它包含下划线,则会出现错误: URI::InvalidURIError: the scheme http does not accept registry part: sub_domain.domain.com (or bad hostname?) URI::InvalidURIError:方案http不接受注册表部分:sub_domain.domain.com(或
resp = open("http://sub_domain.domain.com")
如果它包含下划线,则会出现错误:
URI::InvalidURIError: the scheme http does not accept registry part: sub_domain.domain.com (or bad hostname?)
URI::InvalidURIError:方案http不接受注册表部分:sub_domain.domain.com(或坏主机名?)
我理解这是因为根据RFC,URL只能包含字母和数字。有什么解决办法吗?这样的域名不能包含下划线。这是DNS标准的一部分。你是想用破折号(
-
)吗
即使openuri没有抛出错误,这样的命令也毫无意义。为什么?因为它无法解析这样的域名。充其量只能得到一个未知主机
错误。您无法使用\uu
注册域名,即使运行自己的专用DNS服务器,使用\u
也违反规范。你可以改变规则并允许它(通过修改DNS服务器软件),但是你的操作系统的DNS解析器将不支持它,你的路由器的DNS软件也不支持它
解决方案:不要尝试在DNS名称中使用
。
。它在任何地方都不起作用,而且违反了规范这看起来像是URI中的一个bug,而URI open、HttpParty和许多其他gem都使用了URI.parse
这里有一个解决方法:
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")
我建议使用路缘宝石:它只包装libcurl。下面是一个简单的示例,它将自动执行重定向并打印响应代码和响应正文:
rsp = Curl::Easy.http_get(url){|curl| curl.follow_location = true; curl.max_redirects=10;}
puts rsp.response_code
puts rsp.body_str
我通常避免使用ruby URI类,因为它们与规范太过严格,正如你所知,web是一个狂野的西部:)Curl/curb像champ一样处理我抛出的每个url。我的rails应用程序中的这个初始值设定项似乎使URI.parse至少能够工作:
#config/initializers/uri_underline.rb
类URI::泛型
def使用注册表检查初始化注册表(方案,
用户信息、主机、端口、注册表、,
路径,不透明,
查询
碎片,
parser=默认的\u解析器,
arg_check=false)
如果%w(http https).include?(scheme)&&host.nil?&&注册表=~/_/
在没有注册表检查的情况下初始化注册表(scheme、userinfo、注册表、端口、nil、path、不透明、查询、片段、解析器、arg\u检查)
其他的
在没有注册表检查的情况下初始化注册表(方案、用户信息、主机、端口、注册表、路径、不透明、查询、片段、解析器、参数检查)
结束
结束
别名\u方法\u链:初始化,:注册表\u检查
结束
URI
对url的外观有一个老式的概念
要绕过这个问题:
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!
别忘了
gem安装可寻址的这里是另一个丑陋的黑客,不需要gem:
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
我在尝试使用gem update/gem install等时也遇到了同样的错误。因此,我改用了IP地址,现在一切正常。这里有一个补丁,可以解决各种情况下(rest客户端、开放uri等)的问题,而无需使用外部gem或重写uri的部分。解析:
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
资料来源:
Ruby core有一个悬而未决的问题:对于任何遇到这个问题的人:
Ruby的URI.parse过去是基于RFC2396(1998年8月发布),请参见
但是从Ruby2.2URI开始,如果您使用的是现代版本,那么现在就不需要猴子补丁了。不,我的意思就是下划线。正如我所提到的,我知道这是标准所不允许的,但也有类似的URL(例如在livejournal.com上),我必须处理它们。@Arty啊,我还没有意识到像livejournal这样的大玩家会允许这样的RFC破坏。嗯,我不知道:呃,下划线不是保留字符。它是无保留的。不仅仅是livejournal可以做到这一点,Windows允许在机器名中使用下划线,这样你就可以得到一个有下划线的坏主机名。诚如Tin Man所说,由于下划线是无保留字符,因此在通用URI的主机名部分允许使用下划线,但这与Earlz所说的并不矛盾,即您不能(成功地)在DNS中使用此类主机名。URI中允许它的事实并不意味着它将实际解析,这可能是合理的,因为注册的域和可解析的主机不是URI的唯一可能用途。子域允许有下划线。这是一个丑陋的黑客,但它的工作。问题是,我们的一个合作伙伴强迫我们使用这个域名,我们甚至必须将它添加到所有服务器上的主机文件中,因为它无法解决。。。非常好<代码>可寻址::URI
比ruby core的URI更接近RFC如果您使用Rails,这是最好的解决方案。谢谢@Cluesques这一款很好用。但它给出了一个警告,因为常量DEFAULT_解析器已经存在。为了防止这种情况,我使用了:模块URI original\u verbose,$verbose=$verbose,nil DEFAULT\u PARSER=PARSER.new(:HOSTNAME=>“(?:(?:[a-zA-Z\\d](?:[-\\u a-zA-Z\\d]*[a-zA-Z\\d])\\)*(?:[a-zA-Z](?:[-\\u a-zA-zA-Z\\d]*[a-zA-Z\\d])\.)$VERBOSE=original_VERBOSE end`这也解决了我在使用URI.extract时遇到的问题,它在子域中带有下划线的链接上断开。