检查URL是否存在于Ruby中
我将如何去检查是否存在使用Ruby的URL?
例如,对于URL
https://google.com
结果应该是truthy ,但对于URL
https://no.such.domain
要么
https://stackoverflow.com/no/such/path
结果应该是错误的
使用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)
对不起,这个迟到的答复,但我认为这是一个更好的答案。
有三种方法来看这个问题:
- 严格检查URL是否存在
- 检查您是否正在请求URL correclty
- 检查是否可以正确请求,服务器可以正确回答
1.严格检查URL是否存在
而200
意味着服务器回答该URL(因此,该URL存在),回答其他状态代码并不意味着该URL不存在。 例如,回答302 - redirected
意味着该URL存在并正在redirect到另一个。 在浏览的同时,对于最终用户来说, 302
多次的performance与200
相同。 如果URL存在,可以返回的其他状态代码是500 - internal server error
。 毕竟,如果URL不存在,那么应用程序服务器如何处理您的请求,而不是返回404 - not found
?
所以当URL不存在时,实际上只有两种情况:当服务器不存在或服务器存在时,但找不到给定的URLpath不存在。 因此,检查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
2.检查您是否正在请求URL correclty
但是, 大多数情况下我们并不感兴趣,看看是否存在一个URL,但如果我们可以访问它 。 幸运的是,查看HTTP状态代码系列,即4xx
系列,其中声明客户端错误(因此,在您身边的错误,这意味着您没有正确请求页面,没有任何权限或任何)。 这是一个很好的错误,以检查您是否可以访问此页面。 从wiki:
4xx类状态码用于客户端似乎有错误的情况。 除了响应HEAD请求之外,服务器应该包含一个包含错误情况解释的实体,以及它是临时还是永久状态。 这些状态码适用于任何请求方法。 用户代理应该向用户显示任何包含的实体。
所以下面的代码确保URL存在,你可以访问它 :
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
3.检查是否可以正确请求,服务器可以正确回答
就像4xx
系列检查是否可以访问URL一样, 5xx
系列检查服务器是否有任何问题回答您的请求。 大部分时间这个家庭的错误是服务器本身的问题,希望他们正在解决这个问题。 如果您需要现在能够访问该页面并获得正确的答案 ,则应确保答案不是来自4xx
或5xx
系列,如果您被redirect,则redirect的页面可以正确回答。 与(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
Net::HTTP
工作,但如果你能在stdlib之外工作, 法拉第更好。
Faraday.head(the_url).status == 200
(200是一个成功的代码,假设这就是你的意思是“存在”。)
你应该阅读这篇文章:
validationRuby on Rails中的URL / URI
西蒙娜的回答对我很有帮助。
这是一个根据URL有效性返回true / false的版本,它处理redirect:
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