class RDF::Util::File::NetHttpAdapter

Net::HTTP adapter to retrieve resources without additional dependencies @since 1.2

Public Class Methods

open_url(base_uri, options) click to toggle source

@see RDF::Util::File::HttpAdapter.open_url @param [String] base_uri to open @param [Hash{Symbol => Object}] options @return [RemoteDocument, Object] A {RemoteDocument}. If a block is given, the result of evaluating the block is returned. @raise [IOError] if not found

# File lib/rdf/util/file.rb, line 129
def self.open_url(base_uri, options)
  ssl_verify = options[:verify_none] ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER

  redirect_count = 0
  max_redirects = 5
  parsed_url = ::URI.parse(base_uri)
  parsed_proxy = ::URI.parse(options[:proxy].to_s)
  base_uri = parsed_url.to_s
  remote_document = nil

  until remote_document do
    Net::HTTP::start(parsed_url.host, parsed_url.port,
                    parsed_proxy.host, parsed_proxy.port,
                    open_timeout: 60 * 1000,
                    use_ssl: parsed_url.scheme == 'https',
                    verify_mode: ssl_verify
    ) do |http|
      request = Net::HTTP::Get.new(parsed_url.request_uri, headers(options))
      http.request(request) do |response|
        case response
        when Net::HTTPSuccess
          # found object

          # Normalize headers using symbols
          response_headers = response.to_hash.inject({}) do |out, (key, value)|
            out[key.gsub(/-/, '_').downcase.to_sym] = %w{ set-cookie }.include?(key.downcase) ? value : value.first
            out
          end

          # If a Location is returned, it defines the base resource for this file, not it's actual ending location
          document_options = {
            base_uri:     RDF::URI(response["Location"] ? response["Location"] : base_uri),
            code:         response.code.to_i,
            content_type: response.content_type,
            headers:      response_headers
          }.merge(response.type_params)
          document_options[:last_modified] = DateTime.parse(response["Last-Modified"]) if response["Last-Modified"]

          remote_document = RemoteDocument.new(response.body, document_options)
        when Net::HTTPRedirection
          # Follow redirection
          raise IOError, "Too many redirects" if (redirect_count += 1) > max_redirects

          # Location may be relative
          parsed_url = ::URI.join(base_uri, response["Location"])

          base_uri = parsed_url.to_s
        else
          raise IOError, "<#{parsed_url}>: #{response.message}(#{response.code})"
        end
      end
    end
  end
  remote_document
end