如何检查使用Ruby的URL是否存在?检查Ruby中是否存在URL
例如,对于URL
https://google.com
结果应该是truthy,但对于网址
https://no.such.domain
或
https://stackoverflow.com/no/such/path
结果应该是falsey
如何检查使用Ruby的URL是否存在?检查Ruby中是否存在URL
例如,对于URL
https://google.com
结果应该是truthy,但对于网址
https://no.such.domain
或
https://stackoverflow.com/no/such/path
结果应该是falsey
使用Net::HTTP库。
require "net/http"
url = URI.parse("http://www.google.com/")
req = Net::HTTP.new(url.host, url.port)
res = req.request_head(url.path)
此时res
是包含请求的结果的Net::HTTPResponse对象。然后,您可以检查响应代码:
do_something_with_it(url) if res.code == "200"
注意:要检查https
基于URL,use_ssl
属性应该是true
为:
require "net/http"
url = URI.parse("https://www.google.com/")
req = Net::HTTP.new(url.host, url.port)
req.use_ssl = true
res = req.request_head(url.path)
重定向怎么办? 302 http代码 – 2014-03-23 19:07:44
在生产中,对于每一个URL,这是返回我200代码.. 我已经解析了这个URL,并给了我200 OK ...但是哪个是错的......这里有什么问题?任何想法? 注意:这在Local Env中工作正常。 – 2016-10-06 11:34:40
你应该看看这篇文章:
Simone的回答是对我很有帮助。
下面是根据URL有效性返回true/false一个版本,它处理重定向:
require 'net/http'
require 'set'
def working_url?(url, max_redirects=6)
response = nil
seen = Set.new
loop do
url = URI.parse(url)
break if seen.include? url.to_s
break if seen.size > max_redirects
seen.add(url.to_s)
response = Net::HTTP.new(url.host, url.port).request_head(url.path)
if response.kind_of?(Net::HTTPRedirection)
url = response['location']
else
break
end
end
response.kind_of?(Net::HTTPSuccess) && url.to_s
end
如果服务器不支持HEAD请求,该怎么办? – 2017-11-12 16:04:46
对不起,这个后期的答复,但我认为这deservers一个更好的答案。
有三种方式来看待这个问题:
虽然200
意味着服务器回答该URL(因此该URL存在),但回答其他状态码并不意味着该URL不存在。例如,回答302 - redirected
意味着该URL存在并正在重定向到另一个URL。浏览时,302
多次表现与最终用户的200
相同。如果URL存在,可以返回的其他状态代码是500 - internal server error
。毕竟,如果URL不存在,那么应用程序服务器如何处理您的请求,而仅返回404 - not found
?
所以实际上只有一种情况下,当一个URL不存在时:当服务器不存在或当服务器存在但无法找到给定的URL路径不存在。 因此,检查URL是否存在的唯一方法是检查服务器是否应答并且返回代码不是404.以下代码就是这样做的。
require "net/http"
def url_exist?(url_string)
url = URI.parse(url_string)
req = Net::HTTP.new(url.host, url.port)
req.use_ssl = (url.scheme == 'https')
path = url.path if url.path.present?
res = req.request_head(path || '/')
res.code != "404" # false if returns 404 - not found
rescue Errno::ENOENT
false # false if can't find the server
end
然而,大部分的时间我们都没有兴趣看有没有存在的网址,但如果能访问它。幸运的是,看到HTTP status codes系列,即4xx
系列,其中声明客户端错误(因此,您身边的错误,这意味着您没有正确请求页面,没有任何权限)。这是一个很好的错误来检查您是否可以访问此页面。从维基:
The 4xx class of status code is intended for cases in which the client seems to have erred. Except when responding to a HEAD request, the server should include an entity containing an explanation of the error situation, and whether it is a temporary or permanent condition. These status codes are applicable to any request method. User agents should display any included entity to the user.
所以下面的代码确认网址存在,并且您可以访问它:
require "net/http"
def url_exist?(url_string)
url = URI.parse(url_string)
req = Net::HTTP.new(url.host, url.port)
req.use_ssl = (url.scheme == 'https')
path = url.path if url.path.present?
res = req.request_head(path || '/')
if res.kind_of?(Net::HTTPRedirection)
url_exist?(res['location']) # Go after any redirect and make sure you can access the redirected URL
else
res.code[0] != "4" #false if http code starts with 4 - error on your side.
end
rescue Errno::ENOENT
false #false if can't find the server
end
就像4xx
家族检查您是否可以访问URL一样,5xx
系列会检查服务器是否有任何问题回答您的请求。大多数时候这个家族的错误是服务器本身的问题,希望他们正在努力解决它。如果您需要能够访问该页面并现在得到正确的答案,您应该确保答案不是来自4xx
或5xx
系列,并且如果您被重定向,则重定向页面可以正确回答。如此多的相似(2),你可以简单地使用下面的代码:
require "net/http"
def url_exist?(url_string)
url = URI.parse(url_string)
req = Net::HTTP.new(url.host, url.port)
req.use_ssl = (url.scheme == 'https')
path = url.path if url.path.present?
res = req.request_head(path || '/')
if res.kind_of?(Net::HTTPRedirection)
url_exist?(res['location']) # Go after any redirect and make sure you can access the redirected URL
else
! %W(4 5).include?(res.code[0]) # Not from 4xx or 5xx families
end
rescue Errno::ENOENT
false #false if can't find the server
end
如果你用https-urls做这个,你可能会得到一个'Net :: HTTPBadResponse:错误的状态行'错误。这是因为你必须告诉Net:HTTP来使用ssl。为了使它适用于https,也可以使用'req.use_ssl =(url。方案=='https')'调用'request_head'之前 – 2014-01-06 08:29:13
@YoLudke感谢您的贡献 – fotanus 2014-01-06 10:23:57
另一件事:如果您请求(或重定向转到)'http://www.example.com'(不带尾部' /'),那么你会得到一个'ArgumentError:HTTP请求路径为空'。这可以通过将'res = req.request_head(url.path)'行改为'path = url.path if url.path.present?'和'req.request_head(path ||'/')' – 2014-01-08 08:49:04
问题是不够好,符合我的谷歌搜索,答案是有价值 – kranzky 2017-01-27 04:13:00
我同意。这个问题很有用。 – 2017-03-24 01:43:40
我认为这是一个有用的答案很好的问题。它被关闭的原因(“必须证明最低限度的理解”)在SO上不再有效。我编辑了这个问题来添加一些例子。那么,我认为这个问题现在可以重新开放了。 – 2017-07-08 16:45:21