From ad96f0090ac44a63720368b46ddd685e4354571a Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 29 May 2010 10:54:27 -0700 Subject: [PATCH] Properly download boxes from HTTPS sources. [closes GH-84] --- lib/vagrant.rb | 2 +- lib/vagrant/downloaders/http.rb | 46 +++++++++++++++++---------- test/vagrant/downloaders/http_test.rb | 26 ++++++++++----- vagrant.gemspec | 2 +- 4 files changed, 50 insertions(+), 26 deletions(-) diff --git a/lib/vagrant.rb b/lib/vagrant.rb index 95316e7b7..61759eca6 100644 --- a/lib/vagrant.rb +++ b/lib/vagrant.rb @@ -2,7 +2,7 @@ libdir = File.join(File.dirname(__FILE__), "vagrant") PROJECT_ROOT = File.join(libdir, '..', "..") unless defined?(PROJECT_ROOT) # First, load the various libs which Vagrant requires -%w{tempfile open-uri json pathname logger uri net/http virtualbox net/ssh archive/tar/minitar +%w{tempfile json pathname logger virtualbox net/ssh archive/tar/minitar net/scp fileutils mario}.each do |lib| require lib end diff --git a/lib/vagrant/downloaders/http.rb b/lib/vagrant/downloaders/http.rb index f4a4bab21..fc11751a7 100644 --- a/lib/vagrant/downloaders/http.rb +++ b/lib/vagrant/downloaders/http.rb @@ -1,3 +1,8 @@ +require 'net/http' +require 'net/https' +require 'open-uri' +require 'uri' + module Vagrant module Downloaders # Downloads a file from an HTTP URL to a temporary file. This @@ -11,25 +16,34 @@ module Vagrant end def download!(source_url, destination_file) - Net::HTTP.get_response(URI.parse(source_url)) do |response| - total = response.content_length - progress = 0 - segment_count = 0 + uri = URI.parse(source_url) + http = Net::HTTP.new(uri.host, uri.port) + if uri.scheme == "https" + http.use_ssl = true + http.verify_mode = OpenSSL::SSL::VERIFY_NONE + end - response.read_body do |segment| - # Report the progress out - progress += segment.length - segment_count += 1 + http.start do |h| + h.request_get(uri.request_uri) do |response| + total = response.content_length + progress = 0 + segment_count = 0 - # Progress reporting is limited to every 25 segments just so - # we're not constantly updating - if segment_count % 25 == 0 - env.logger.report_progress(progress, total) - segment_count = 0 + response.read_body do |segment| + # Report the progress out + progress += segment.length + segment_count += 1 + + # Progress reporting is limited to every 25 segments just so + # we're not constantly updating + if segment_count % 25 == 0 + env.logger.report_progress(progress, total) + segment_count = 0 + end + + # Store the segment + destination_file.write(segment) end - - # Store the segment - destination_file.write(segment) end end diff --git a/test/vagrant/downloaders/http_test.rb b/test/vagrant/downloaders/http_test.rb index 4730ed13a..8fb858196 100644 --- a/test/vagrant/downloaders/http_test.rb +++ b/test/vagrant/downloaders/http_test.rb @@ -5,28 +5,38 @@ class HttpDownloaderTest < Test::Unit::TestCase @downloader, @tempfile = mock_downloader(Vagrant::Downloaders::HTTP) @downloader.stubs(:report_progress) @downloader.stubs(:complete_progress) - @uri = "foo.box" + @uri = "http://google.com/" end context "downloading" do setup do - @parsed_uri = mock("parsed") - URI.stubs(:parse).with(@uri).returns(@parsed_uri) + @parsed_uri = URI.parse(@uri) + @http = Net::HTTP.new(@parsed_uri.host, @parsed_uri.port) + Net::HTTP.stubs(:new).returns(@http) + @http.stubs(:start) end - should "parse the URI and use that parsed URI for Net::HTTP" do - URI.expects(:parse).with(@uri).returns(@parsed_uri).once - Net::HTTP.expects(:get_response).with(@parsed_uri).once + should "create a proper net/http object" do + Net::HTTP.expects(:new).with(@parsed_uri.host, @parsed_uri.port).once.returns(@http) + @http.expects(:start) + @downloader.download!(@uri, @tempfile) + end + + should "enable SSL if scheme is https" do + @uri = "https://google.com/" + @http.expects(:use_ssl=).with(true).once @downloader.download!(@uri, @tempfile) end should "read the body of the response and place each segment into the file" do + h = mock("http") response = mock("response") response.stubs(:content_length) segment = mock("segment") segment.stubs(:length).returns(7) - Net::HTTP.stubs(:get_response).yields(response) + @http.stubs(:start).yields(h) + h.expects(:request_get).with(@parsed_uri.request_uri).once.yields(response) response.expects(:read_body).once.yields(segment) @tempfile.expects(:write).with(segment).once @@ -43,7 +53,7 @@ class HttpDownloaderTest < Test::Unit::TestCase should "return false if there are no extract results" do URI.expects(:extract).returns([]) assert !Vagrant::Downloaders::HTTP.match?('foo') - end + end end context "reporting progress" do diff --git a/vagrant.gemspec b/vagrant.gemspec index 851da4f96..e411ece35 100644 --- a/vagrant.gemspec +++ b/vagrant.gemspec @@ -9,7 +9,7 @@ Gem::Specification.new do |s| s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version= s.authors = ["Mitchell Hashimoto", "John Bender"] - s.date = %q{2010-05-28} + s.date = %q{2010-05-29} s.default_executable = %q{vagrant} s.description = %q{Vagrant is a tool for building and distributing virtualized development environments.} s.email = ["mitchell.hashimoto@gmail.com", "john.m.bender@gmail.com"]