Mở đầu

Mục tiêu của bài viết là viết một đoạn mã kiểm tra một url cho trước còn sống hay đã chết.

Một url được xem là đã chết nếu mở trên trình duyệt bị lỗi. Đồng nghĩa với việc khi check status trả về của url thì phải check tới cả các redirect url nữa (khi status trả về 302)

Mục tiêu:

  • Nếu request tới url và nhận được status = 200 thì url vẫn hoạt động bình thường.
  • Nếu request tới url và nhận được status = 3xx thì phải check các redirect url tương ứng.
  • Chỉ check tối đa 10 lần status = 3xx liên tiếp vì có thể có url bị redirect vô hạn lần.

Mã nguồn

def url_exist? url_string, redirect_count = 1
  url_string = "http://#{url_string}" unless url_string.start_with?('http')
  p "check #{url_string}"
  
  begin
    url = URI.parse url_string
  rescue URI::InvalidURIError
    url = URI.parse(URI.escape(url_string))
  end
  
  req = Net::HTTP.new(url.host, url.port)
  req.open_timeout = 5
  req.read_timeout = 5
  req.use_ssl = (url.scheme == 'https')
  
  path = ""
  path += url.request_uri if url.request_uri.present?
  path += "##{url.fragment}" if url.fragment.present?
  path = path.present? ? path : '/'
  
  res = req.request_head(path)
  p res.code
  
  if res.is_a?(Net::HTTPRedirection)
    return false if redirect_count >= 10
    location = res['location']
    location = url.host + location if location.start_with? '/'
    print "Redirect to "
    url_exist?(location, redirect_count + 1) # Go after any redirect and make sure you can access the redirected URL
  else
    ! %w(4 5).include?(res.code[0])
  end
  
rescue => e
  p e
  false
end