Class: Vagrant::Util::Downloader
- Inherits:
-
Object
- Object
- Vagrant::Util::Downloader
- Defined in:
- lib/vagrant/util/downloader.rb
Overview
This class downloads files using various protocols by subprocessing to cURL. cURL is a much more capable and complete download tool than a hand-rolled Ruby library, so we defer to its expertise.
Constant Summary collapse
- USER_AGENT =
Custom user agent provided to cURL so that requests to URL shorteners are properly tracked.
Vagrant/1.7.4 (+https://www.vagrantup.com; ruby2.1.0)
"Vagrant/#{VERSION} (+https://www.vagrantup.com; #{RUBY_ENGINE}#{RUBY_VERSION}) #{ENV['VAGRANT_USER_AGENT_PROVISIONAL_STRING']}".strip.freeze
- SILENCED_HOSTS =
Hosts that do not require notification on redirect
[ "vagrantcloud.com".freeze, "vagrantup.com".freeze ].freeze
Instance Attribute Summary collapse
-
#destination ⇒ Object
readonly
Returns the value of attribute destination.
-
#headers ⇒ Object
Returns the value of attribute headers.
-
#source ⇒ Object
Returns the value of attribute source.
Instance Method Summary collapse
-
#download! ⇒ Object
This executes the actual download, downloading the source file to the destination with the given options used to initialize this class.
-
#head ⇒ Object
Does a HEAD request of the URL and returns the output.
-
#initialize(source, destination, options = nil) ⇒ Downloader
constructor
A new instance of Downloader.
Constructor Details
#initialize(source, destination, options = nil) ⇒ Downloader
Returns a new instance of Downloader.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/vagrant/util/downloader.rb', line 39 def initialize(source, destination, =nil) ||= {} @logger = Log4r::Logger.new("vagrant::util::downloader") @source = source.to_s @destination = destination.to_s begin url = URI.parse(@source) if url.scheme && url.scheme.start_with?("http") && url.user auth = "#{CGI.unescape(url.user)}" auth += ":#{CGI.unescape(url.password)}" if url.password url.user = nil url.password = nil [:auth] ||= auth @source = url.to_s end rescue URI::InvalidURIError # Ignore, since its clearly not HTTP end # Get the various optional values @auth = [:auth] @ca_cert = [:ca_cert] @ca_path = [:ca_path] @continue = [:continue] @headers = Array([:headers]) @insecure = [:insecure] @ui = [:ui] @client_cert = [:client_cert] @location_trusted = [:location_trusted] @checksums = { :md5 => [:md5], :sha1 => [:sha1], :sha256 => [:sha256], :sha384 => [:sha384], :sha512 => [:sha512] }.compact @extra_download_options = [:box_extra_download_options] || [] # If on Windows SSL revocation checks should be best effort. More context # for this usage can be found in the following links: # # https://github.com/curl/curl/issues/3727 # https://github.com/curl/curl/pull/4981 if Platform.windows? @ssl_revoke_best_effort = ![:disable_ssl_revoke_best_effort] end end |
Instance Attribute Details
#destination ⇒ Object (readonly)
Returns the value of attribute destination.
36 37 38 |
# File 'lib/vagrant/util/downloader.rb', line 36 def destination @destination end |
#headers ⇒ Object
Returns the value of attribute headers.
37 38 39 |
# File 'lib/vagrant/util/downloader.rb', line 37 def headers @headers end |
#source ⇒ Object
Returns the value of attribute source.
35 36 37 |
# File 'lib/vagrant/util/downloader.rb', line 35 def source @source end |
Instance Method Details
#download! ⇒ Object
This executes the actual download, downloading the source file to the destination with the given options used to initialize this class.
If this method returns without an exception, the download succeeded. An exception will be raised if the download failed.
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/vagrant/util/downloader.rb', line 94 def download! # This variable can contain the proc that'll be sent to # the subprocess execute. data_proc = nil extra_subprocess_opts = {} if @ui # If we're outputting progress, then setup the subprocess to # tell us output so we can parse it out. extra_subprocess_opts[:notify] = :stderr data_proc = Vagrant::Util::CurlHelper.capture_output_proc(@logger, @ui, @source) end @logger.info("Downloader starting download: ") @logger.info(" -- Source: #{@source}") @logger.info(" -- Destination: #{@destination}") retried = false begin # Get the command line args and the subprocess opts based # on our downloader settings. , = self. += ["--output", @destination] << @source # Merge in any extra options we set .merge!(extra_subprocess_opts) # Go! execute_curl(, , &data_proc) rescue Errors::DownloaderError => e # If we already retried, raise it. raise if retried @logger.error("Exit code: #{e.extra_data[:code]}") # If its any error other than 33, it is an error. raise if e.extra_data[:code].to_i != 33 # Exit code 33 means that the server doesn't support ranges. # In this case, try again without resume. @logger.error("Error is server doesn't support byte ranges. Retrying from scratch.") @continue = false retried = true retry ensure # If we're outputting to the UI, clear the output to # avoid lingering progress meters. if @ui @ui.clear_line # Windows doesn't clear properly for some reason, so we just # output one more newline. @ui.detail("") if Platform.windows? end end validate_download!(@source, @destination, @checksums) # Everything succeeded true end |
#head ⇒ Object
Does a HEAD request of the URL and returns the output.
159 160 161 162 163 164 165 166 167 |
# File 'lib/vagrant/util/downloader.rb', line 159 def head , = self. .unshift("-I") << @source @logger.info("HEAD: #{@source}") result = execute_curl(, ) result.stdout end |