Sha256: f79d7edf359f4cedafc575bc8756a838dddf7ba7474907c3f7854cfc4e8deec9

Contents?: true

Size: 1.76 KB

Versions: 1

Compression:

Stored size: 1.76 KB

Contents

module Flavicon
  class Finder < Struct.new(:url)
    require 'uri'
    require 'net/http'
    require 'nokogiri'

    TooManyRedirects = Class.new(StandardError)

    def find
      response, resolved = request(url)
      favicon_url = extract_from_html(response.body, resolved) || default_path(resolved)
      valid_favicon_url?(favicon_url) ? favicon_url : nil
    end

    def valid_favicon_url?(url)
      response, _ = request(url)
      response.is_a?(Net::HTTPSuccess) && response.body.to_s != '' && response.content_type =~ /image/i
    end

    def extract_from_html(html, url)
      link = Nokogiri::HTML(html).css('head link').find do |link|
        link[:rel] =~ /\A(shortcut )?icon\z/i
      end

      URI.join(url, link[:href]).to_s if link
    end

    def default_path(url)
      URI.join(url, '/favicon.ico').to_s
    end

    def request(url, limit = 10)
      raise TooManyRedirects if limit < 0

      uri = URI.parse(url)
      http = Net::HTTP.new(uri.host, uri.port)
      request = Net::HTTP::Get.new(uri.request_uri)

      if uri.scheme == 'https'
        http.use_ssl = true
        http.verify_mode = OpenSSL::SSL::VERIFY_NONE
      end

      response = http.request(request)

      if response.is_a? Net::HTTPRedirection
        request(extract_location(response, url), limit - 1)
      else
        return response, url
      end
    end

    # While the soon-to-be obsolete IETF standard RFC 2616 (HTTP 1.1) requires a complete absolute URI for redirection,
    # the most popular web browsers tolerate the passing of a relative URL as the value for a Location header field.
    # Consequently, the current revision of HTTP/1.1 makes relative URLs conforming.
    def extract_location(response, url)
      URI.join(url, response['location']).to_s
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
flavicon-0.1.0 lib/flavicon/finder.rb