indieweb/link_rel_parser-ruby

View on GitHub
lib/link_rel_parser.rb

Summary

Maintainability
A
1 hr
Test Coverage
require "active_support"
require "active_support/core_ext/object/blank"
require "link_rel_parser/version"
require "metainspector"
require "uri"

module LinkRelParser
  class << self

    # Public: Parse out LINK headers with a REL value.
    #
    # url - URL to get HTTP HEAD Link (and effective/x-extended) rels.
    #
    # Examples
    #
    #   LinkRelParser.parse("http://example.com")
    #   # =>
    #     {
    #       status: "200",
    #       type:   "text/HTML",
    #       rels:   { "pingback" => "http://www.example.com/xmlrpc.php", "indieauth" => "https://indieauth.com" }
    #     }
    #
    # Returns a hash of HTTP status code, content type, and LINKs with a REL value or an empty {}
    def parse(url)
      page         = MetaInspector.new(url)
      header_links = page.response.headers[:link]

      # Convert X-Pingback to a Link header and have common code handle it
      unless page.response.headers["x-pingback"].nil?
        header_links << %Q{, <#{header_links['x-pingback']}>; rel="pingback"}
      end

      output = {
        status: page.response.status,
        type:   page.response["content-type"],
        rels:   link_rels(header_links)
      }

      output[:rels].blank? ? {} : output
    end

    # Internal: Parse out the HTTP LINK headers with a REL value.
    #
    # headers  - string to HTTP headers.
    # base_url - optional base URL to resolve relative URLs (default: nil).
    #
    # Examples
    #
    #   link_rels(headers)
    #   # => { "pingback" => "http://www.example.com/xmlrpc.php", "indieauth" => "https://indieauth.com" }
    #
    # Returns a hash of LINK name and REL value or an empty {}
    def link_rels(headers, base_url: nil)
      links = {}

      unless headers.nil?
        headers.split(", ").each do |link, index|
          section = link.split(';')
          url     = section[0][/<(.*)>/,1]

          # ignore link headers without rel
          if section[1] =~ /rel=/
            rel = section[1][/rel="*(.*)"*/,1].gsub(/"$/, "")
            rel.split.each do |name|

              unless base_url.blank?
                uri      = URI.parse(base_url)
                path     = url.gsub(%r{^/*}, "")
                uri.path = "/" + path
                url      = uri.normalize
              end

              links[name] = url
            end
          end
        end
      end

      links
    end

  end
end