Class: Gem::RemoteFetcher (Ruby 2.7.2)
Description: Class : Gem::RemoteFetcher - Ruby 2.7.2

### Home Classes Methods

### In Files

- rubygems/remote_fetcher.rb
- rubygems/request.rb
- rubygems/test_utilities.rb

### Parent

Object

### Namespace

- CLASS Gem::RemoteFetcher::FetchError
- CLASS Gem::RemoteFetcher::UnknownHostError

### Methods

- ::fetcher
- ::fetcher=
- ::new
- #cache_update_path
- #close_all
- #download
- #download_to_cache
- #fetch_file
- #fetch_http
- #fetch_https
- #fetch_path
- #fetch_s3
- #fetch_size
- #https?
- #request
- #s3_uri_signer

### Included Modules

- Gem::UserInteraction
- Gem::UriParsing

### Class/Module Index

Quicksearch

- Bundler
- Gem::AvailableSet
- Gem::BasicSpecification
- Gem::BundlerVersionFinder
- Gem::Command
- Gem::CommandLineError
- Gem::CommandManager
- Gem::Commands
- Gem::Commands::BuildCommand
- Gem::Commands::CertCommand
- Gem::Commands::CheckCommand
- Gem::Commands::CleanupCommand
- Gem::Commands::ContentsCommand
- Gem::Commands::DependencyCommand
- Gem::Commands::EnvironmentCommand
- Gem::Commands::FetchCommand
- Gem::Commands::GenerateIndexCommand
- Gem::Commands::HelpCommand
- Gem::Commands::InfoCommand
- Gem::Commands::InstallCommand
- Gem::Commands::ListCommand
- Gem::Commands::LockCommand
- Gem::Commands::MirrorCommand
- Gem::Commands::OpenCommand
- Gem::Commands::OutdatedCommand
- Gem::Commands::OwnerCommand
- Gem::Commands::PristineCommand
- Gem::Commands::PushCommand
- Gem::Commands::QueryCommand
- Gem::Commands::RdocCommand
- Gem::Commands::SearchCommand
- Gem::Commands::ServerCommand
- Gem::Commands::SetupCommand
- Gem::Commands::SetupCommand::MakeDirs
- Gem::Commands::SigninCommand
- Gem::Commands::SignoutCommand
- Gem::Commands::SourcesCommand
- Gem::Commands::SpecificationCommand
- Gem::Commands::StaleCommand
- Gem::Commands::UninstallCommand
- Gem::Commands::UnpackCommand
- Gem::Commands::UpdateCommand
- Gem::Commands::WhichCommand
- Gem::Commands::YankCommand
- Gem::ConfigFile
- Gem::ConflictError
- Gem::ConsoleUI
- Gem::DefaultUserInteraction
- Gem::Dependency
- Gem::DependencyError
- Gem::DependencyInstaller
- Gem::DependencyList
- Gem::DependencyRemovalException
- Gem::DependencyResolutionError
- Gem::Deprecate
- Gem::Doctor
- Gem::DocumentError
- Gem::EndOfYAMLException
- Gem::ErrorReason
- Gem::Exception
- Gem::Ext
- Gem::Ext::BuildError
- Gem::Ext::Builder
- Gem::Ext::CmakeBuilder
- Gem::Ext::ConfigureBuilder
- Gem::Ext::ExtConfBuilder
- Gem::Ext::RakeBuilder
- Gem::FakeFetcher
- Gem::FilePermissionError
- Gem::FormatException
- Gem::GemNotFoundException
- Gem::GemNotInHomeException
- Gem::GemRunner
- Gem::GemcutterUtilities
- Gem::ImpossibleDependenciesError
- Gem::Indexer
- Gem::InstallError
- Gem::InstallUpdateOptions
- Gem::Installer
- Gem::Installer::FakePackage
- Gem::InstallerTestCase
- Gem::InvalidSpecificationException
- Gem::Licenses
- Gem::List
- Gem::LoadError
- Gem::LocalRemoteOptions
- Gem::MissingSpecError
- Gem::MissingSpecVersionError
- Gem::MockGemUi
- Gem::MockGemUi::InputEOFError
- Gem::MockGemUi::SystemExitException
- Gem::MockGemUi::TTY
- Gem::MockGemUi::TermError
- Gem::NameTuple
- Gem::NoAliasYAMLTree
- Gem::OperationNotSupportedError
- Gem::Package::DigestIO
- Gem::Package::Error
- Gem::Package::FormatError
- Gem::Package::NonSeekableIO
- Gem::Package::Old
- Gem::Package::PathError
- Gem::Package::TarHeader
- Gem::Package::TarInvalidError
- Gem::Package::TarReader
- Gem::Package::TarReader::Entry
- Gem::Package::TarReader::UnexpectedEOF
- Gem::Package::TarTestCase
- Gem::Package::TarWriter
- Gem::Package::TarWriter::BoundedStream
- Gem::Package::TarWriter::FileOverflow
- Gem::Package::TarWriter::RestrictedStream
- Gem::Package::TooLongFileName
- Gem::PackageTask
- Gem::PathSupport
- Gem::Platform
- Gem::PlatformMismatch
- Gem::RemoteError
- Gem::RemoteFetcher
- Gem::RemoteFetcher::FetchError
- Gem::RemoteFetcher::UnknownHostError
- Gem::RemoteInstallationCancelled
- Gem::RemoteInstallationSkipped
- Gem::RemoteSourceException
- Gem::Request::ConnectionPools
- Gem::Request::ConnectionPools::Net
- Gem::RequestSet
- Gem::RequestSet::GemDependencyAPI
- Gem::RequestSet::Lockfile
- Gem::RequestSet::Lockfile::ParseError
- Gem::RequestSet::Lockfile::Parser
- Gem::RequestSet::Lockfile::Tokenizer
- Gem::Requirement
- Gem::Requirement::BadRequirementError
- Gem::Resolver
- Gem::Resolver::APISet
- Gem::Resolver::APISpecification
- Gem::Resolver::ActivationRequest
- Gem::Resolver::BestSet
- Gem::Resolver::ComposedSet
- Gem::Resolver::Conflict
- Gem::Resolver::CurrentSet
- Gem::Resolver::DependencyRequest
- Gem::Resolver::GitSet
- Gem::Resolver::GitSpecification
- Gem::Resolver::IndexSet
- Gem::Resolver::IndexSpecification
- Gem::Resolver::InstalledSpecification
- Gem::Resolver::InstallerSet
- Gem::Resolver::LocalSpecification
- Gem::Resolver::LockSet
- Gem::Resolver::LockSpecification
- Gem::Resolver::Molinillo
- Gem::Resolver::Molinillo::CircularDependencyError
- Gem::Resolver::Molinillo::Delegates
- Gem::Resolver::Molinillo::Delegates::ResolutionState
- Gem::Resolver::Molinillo::Delegates::SpecificationProvider
- Gem::Resolver::Molinillo::DependencyGraph
- Gem::Resolver::Molinillo::DependencyGraph::Action
- Gem::Resolver::Molinillo::DependencyGraph::AddEdgeNoCircular
- Gem::Resolver::Molinillo::DependencyGraph::DeleteEdge
- Gem::Resolver::Molinillo::DependencyGraph::DetachVertexNamed
- Gem::Resolver::Molinillo::DependencyGraph::Log
- Gem::Resolver::Molinillo::DependencyGraph::Tag
- Gem::Resolver::Molinillo::DependencyGraph::Vertex
- Gem::Resolver::Molinillo::DependencyState
- Gem::Resolver::Molinillo::NoSuchDependencyError
- Gem::Resolver::Molinillo::PossibilityState
- Gem::Resolver::Molinillo::ResolutionState
- Gem::Resolver::Molinillo::Resolver
- Gem::Resolver::Molinillo::Resolver::Resolution
- Gem::Resolver::Molinillo::ResolverError
- Gem::Resolver::Molinillo::SpecificationProvider
- Gem::Resolver::Molinillo::UI
- Gem::Resolver::Molinillo::VersionConflict
- Gem::Resolver::RequirementList
- Gem::Resolver::Set
- Gem::Resolver::SourceSet
- Gem::Resolver::SpecSpecification
- Gem::Resolver::Specification
- Gem::Resolver::Stats
- Gem::Resolver::VendorSet
- Gem::Resolver::VendorSpecification
- Gem::RubyVersionMismatch
- Gem::RuntimeRequirementNotMetError
- Gem::S3URISigner
- Gem::S3URISigner::ConfigurationError
- Gem::S3URISigner::InstanceProfileError
- Gem::SafeYAML
- Gem::Security
- Gem::Security::Exception
- Gem::Security::Policy
- Gem::Security::Signer
- Gem::Security::TrustDir
- Gem::SecurityOption
- Gem::Server
- Gem::SilentUI
- Gem::Source
- Gem::Source::Git
- Gem::Source::Installed
- Gem::Source::Local
- Gem::Source::Lock
- Gem::Source::SpecificFile
- Gem::Source::Vendor
- Gem::SourceFetchProblem
- Gem::SourceList
- Gem::SpecFetcher
- Gem::SpecificGemNotFoundException
- Gem::Specification
- Gem::SpecificationPolicy
- Gem::StreamUI
- Gem::StreamUI::SilentDownloadReporter
- Gem::StreamUI::SilentProgressReporter
- Gem::StreamUI::SimpleProgressReporter
- Gem::StreamUI::ThreadedDownloadReporter
- Gem::StreamUI::VerboseProgressReporter
- Gem::StubSpecification
- Gem::SystemExitException
- Gem::TestCase
- Gem::TestCase::SpecFetcherSetup
- Gem::TestCase::StaticSet
- Gem::Text
- Gem::UninstallError
- Gem::Uninstaller
- Gem::UnsatisfiableDependencyError
- Gem::UriFormatter
- Gem::UriParser
- Gem::UriParsing
- Gem::UserInteraction
- Gem::Util
- Gem::Validator
- Gem::VerificationError
- Gem::Version
- Gem::VersionOption
- Kernel
- Object
- OpenSSL
- TempIO
- YAML::Syck
- YAML::Syck

No matching classes.

# Gem::RemoteFetcher

RemoteFetcher handles the details of fetching gems and gem information from a remote source.

### Attributes

headers[RW]

### Public Class Methods

fetcher() click to toggle source

Cached RemoteFetcher instance.

                   # File rubygems/remote_fetcher.rb, line 64
    def self.fetcher
      @fetcher ||= self.new Gem.configuration[:http_proxy]
    end

fetcher=(fetcher) click to toggle source

                   # File rubygems/test_utilities.rb, line 171
    def self.fetcher=(fetcher)
      @fetcher = fetcher
    end

new(proxy=nil, dns=nil, headers={}) click to toggle source

Initialize a remote fetcher using the source URI and possible proxy information.

`proxy`

- [String]: explicit specification of proxy; overrides any environment

      variable setting

- nil: respect environment variables (HTTP_PROXY, HTTP_PROXY_USER,

      HTTP_PROXY_PASS)

- `:no_proxy`: ignore environment variables and _don't_ use a proxy

`headers`: A set of additional HTTP headers to be sent to the server when

    fetching the gem.

                   # File rubygems/remote_fetcher.rb, line 84
    def initialize(proxy=nil, dns=nil, headers={})
      require 'net/http'
      require 'stringio'
      require 'time'
      require 'uri'

      Socket.do_not_reverse_lookup = true

      @proxy = proxy
      @pools = {}
      @pool_lock = Mutex.new
      @cert_files = Gem::Request.get_cert_files

      @headers = headers
    end

### Public Instance Methods

cache_update_path(uri, path = nil, update = true) click to toggle source

Downloads `uri` to `path` if necessary. If no path is given, it just passes the data.

                   # File rubygems/remote_fetcher.rb, line 296
    def cache_update_path(uri, path = nil, update = true)
      mtime = path && File.stat(path).mtime rescue nil

      data = fetch_path(uri, mtime)

      if data == nil # indicates the server returned 304 Not Modified
        return Gem.read_binary(path)
      end

      if update and path
        Gem.write_binary(path, data)
      end

      data
    end

close_all() click to toggle source

                   # File rubygems/remote_fetcher.rb, line 343
    def close_all
      @pools.each_value {|pool| pool.close_all}
    end

download(spec, source_uri, install_dir = Gem.dir) click to toggle source

Moves the gem `spec` from `source_uri` to the cache dir unless it is already there. If the source_uri is local the gem cache dir copy is always replaced.

                   # File rubygems/remote_fetcher.rb, line 122
    def download(spec, source_uri, install_dir = Gem.dir)
      cache_dir =
        if Dir.pwd == install_dir  # see fetch_command
          install_dir
        elsif File.writable? install_dir
          File.join install_dir, "cache"
        else
          File.join Gem.user_dir, "cache"
        end

      gem_file_name = File.basename spec.cache_file
      local_gem_path = File.join cache_dir, gem_file_name

      FileUtils.mkdir_p cache_dir rescue nil unless File.exist? cache_dir

      source_uri = parse_uri(source_uri)

      scheme = source_uri.scheme

      # URI.parse gets confused by MS Windows paths with forward slashes.
      scheme = nil if scheme =~ /^[a-z]$/i

      # REFACTOR: split this up and dispatch on scheme (eg download_http)
      # REFACTOR: be sure to clean up fake fetcher when you do this... cleaner
      case scheme
      when 'http', 'https', 's3' then
        unless File.exist? local_gem_path
          begin
            verbose "Downloading gem #{gem_file_name}"

            remote_gem_path = source_uri + "gems/#{gem_file_name}"

            self.cache_update_path remote_gem_path, local_gem_path
          rescue FetchError
            raise if spec.original_platform == spec.platform

            alternate_name = "#{spec.original_name}.gem"

            verbose "Failed, downloading gem #{alternate_name}"

            remote_gem_path = source_uri + "gems/#{alternate_name}"

            self.cache_update_path remote_gem_path, local_gem_path
          end
        end
      when 'file' then
        begin
          path = source_uri.path
          path = File.dirname(path) if File.extname(path) == '.gem'

          remote_gem_path = Gem::Util.correct_for_windows_path(File.join(path, 'gems', gem_file_name))

          FileUtils.cp(remote_gem_path, local_gem_path)
        rescue Errno::EACCES
          local_gem_path = source_uri.to_s
        end

        verbose "Using local gem #{local_gem_path}"
      when nil then # TODO test for local overriding cache
        source_path = if Gem.win_platform? && source_uri.scheme &&
                         !source_uri.path.include?(':')
                        "#{source_uri.scheme}:#{source_uri.path}"
                      else
                        source_uri.path
                      end

        source_path = Gem::UriFormatter.new(source_path).unescape

        begin
          FileUtils.cp source_path, local_gem_path unless
            File.identical?(source_path, local_gem_path)
        rescue Errno::EACCES
          local_gem_path = source_uri.to_s
        end

        verbose "Using local gem #{local_gem_path}"
      else
        raise ArgumentError, "unsupported URI scheme #{source_uri.scheme}"
      end

      local_gem_path
    end

download_to_cache(dependency) click to toggle source

Given a name and requirement, downloads this gem into cache and returns the filename. Returns nil if the gem cannot be located.

                   # File rubygems/remote_fetcher.rb, line 107
    def download_to_cache(dependency)
      found, _ = Gem::SpecFetcher.fetcher.spec_for_dependency dependency

      return if found.empty?

      spec, source = found.max_by { |(s,_)| s.version }

      download spec, source.uri
    end

fetch_file(uri, *_) click to toggle source

File Fetcher. Dispatched by `fetch_path`. Use it instead.

                   # File rubygems/remote_fetcher.rb, line 208
    def fetch_file(uri, *_)
      Gem.read_binary Gem::Util.correct_for_windows_path uri.path
    end

fetch_http(uri, last_modified = nil, head = false, depth = 0) click to toggle source

HTTP Fetcher. Dispatched by `fetch_path`. Use it instead.

                   # File rubygems/remote_fetcher.rb, line 215
    def fetch_http(uri, last_modified = nil, head = false, depth = 0)
      fetch_type = head ? Net::HTTP::Head : Net::HTTP::Get
      response   = request uri, fetch_type, last_modified do |req|
        headers.each { |k,v| req.add_field(k,v) }
      end

      case response
      when Net::HTTPOK, Net::HTTPNotModified then
        response.uri = uri if response.respond_to? :uri
        head ? response : response.body
      when Net::HTTPMovedPermanently, Net::HTTPFound, Net::HTTPSeeOther,
           Net::HTTPTemporaryRedirect then
        raise FetchError.new('too many redirects', uri) if depth > 10

        unless location = response['Location']
          raise FetchError.new("redirecting but no redirect location was given", uri)
        end
        location = parse_uri location

        if https?(uri) && !https?(location)
          raise FetchError.new("redirecting to non-https resource: #{location}", uri)
        end

        fetch_http(location, last_modified, head, depth + 1)
      else
        raise FetchError.new("bad response #{response.message} #{response.code}", uri)
      end
    end

Also aliased as: fetch_https
fetch_https(uri, last_modified = nil, head = false, depth = 0) click to toggle source
Alias for: fetch_http
fetch_path(uri, mtime = nil, head = false) click to toggle source

Downloads `uri` and returns it as a String.

                   # File rubygems/remote_fetcher.rb, line 249
    def fetch_path(uri, mtime = nil, head = false)
      uri = parse_uri uri

      unless uri.scheme
        raise ArgumentError, "uri scheme is invalid: #{uri.scheme.inspect}"
      end

      data = send "fetch_#{uri.scheme}", uri, mtime, head

      if data and !head and uri.to_s =~ /\.gz$/
        begin
          data = Gem::Util.gunzip data
        rescue Zlib::GzipFile::Error
          raise FetchError.new("server did not return a valid file", uri)
        end
      end

      data
    rescue Timeout::Error
      raise UnknownHostError.new('timed out', uri)
    rescue IOError, SocketError, SystemCallError,
           *(OpenSSL::SSL::SSLError if defined?(OpenSSL)) => e
      if e.message =~ /getaddrinfo/
        raise UnknownHostError.new('no such name', uri)
      else
        raise FetchError.new("#{e.class}: #{e}", uri)
      end
    end

fetch_s3(uri, mtime = nil, head = false) click to toggle source

                   # File rubygems/remote_fetcher.rb, line 278
    def fetch_s3(uri, mtime = nil, head = false)
      begin
        public_uri = s3_uri_signer(uri).sign
      rescue Gem::S3URISigner::ConfigurationError, Gem::S3URISigner::InstanceProfileError => e
        raise FetchError.new(e.message, "s3://#{uri.host}")
      end
      fetch_https public_uri, mtime, head
    end

fetch_size(uri) click to toggle source

Returns the size of `uri` in bytes.

                   # File rubygems/remote_fetcher.rb, line 315
    def fetch_size(uri)
      response = fetch_path(uri, nil, true)

      response['content-length'].to_i
    end

https?(uri) click to toggle source

                   # File rubygems/remote_fetcher.rb, line 339
    def https?(uri)
      uri.scheme.downcase == 'https'
    end

request(uri, request_class, last_modified = nil) click to toggle source

Performs a Net::HTTP request of type `request_class` on `uri` returning a Net::HTTP response object. request maintains a table of persistent connections to reduce connect overhead.

                   # File rubygems/remote_fetcher.rb, line 328
    def request(uri, request_class, last_modified = nil)
      proxy = proxy_for @proxy, uri
      pool  = pools_for(proxy).pool_for uri

      request = Gem::Request.new uri, request_class, last_modified, pool

      request.fetch do |req|
        yield req if block_given?
      end
    end

s3_uri_signer(uri) click to toggle source

we have our own signing code here to avoid a dependency on the aws-sdk gem

                   # File rubygems/remote_fetcher.rb, line 288
    def s3_uri_signer(uri)
      Gem::S3URISigner.new(uri)
    end