diff --git a/CHANGELOG.md b/CHANGELOG.md index 064a52ccf..23e72ac02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ ##### Enhancements +* `HTTP::perform_head_request` now includes a 1-byte `Range` header in the fallback GET + request. + [Kyle Fleming](https://github.com/kylefleming) + [#425](https://github.com/CocoaPods/Core/pull/425) + * Update Podfile Reference Guide to include `:source` parameter for the `pod` statement [Mark Woollard](https://github.com/mwoollard) [#7359](https://github.com/CocoaPods/CocoaPods/issues/7359) diff --git a/lib/cocoapods-core/http.rb b/lib/cocoapods-core/http.rb index dcb712618..da5c2a8b4 100644 --- a/lib/cocoapods-core/http.rb +++ b/lib/cocoapods-core/http.rb @@ -44,7 +44,7 @@ def self.validate_url(url) begin url = get_actual_url(url) resp = perform_head_request(url) - rescue SocketError, URI::InvalidURIError, REST::Error, REST::DisconnectedError + rescue SocketError, URI::InvalidURIError, REST::Error, REST::Error::Connection resp = nil end @@ -65,7 +65,12 @@ def self.perform_head_request(url) resp = ::REST.head(url, 'User-Agent' => USER_AGENT) if resp.status_code >= 400 - resp = ::REST.get(url, 'User-Agent' => USER_AGENT) + resp = ::REST.get(url, 'User-Agent' => USER_AGENT, + 'Range' => 'bytes=0-0') + + if resp.status_code >= 400 + resp = ::REST.get(url, 'User-Agent' => USER_AGENT) + end end resp diff --git a/spec/http_spec.rb b/spec/http_spec.rb index 58ab4577d..d912e5a30 100644 --- a/spec/http_spec.rb +++ b/spec/http_spec.rb @@ -2,6 +2,10 @@ module Pod describe HTTP do + after do + WebMock.reset! + end + describe 'In general' do it 'can resolve redirects' do WebMock::API.stub_request(:head, /redirect/).to_return( @@ -28,7 +32,7 @@ module Pod response.success?.should.be.true end - it 'is resilient to HEAD errros' do + it 'is resilient to HEAD errors' do WebMock::API.stub_request(:head, /foo/).to_return(:status => 404) WebMock::API.stub_request(:get, /foo/).to_return(:status => 200) @@ -50,13 +54,37 @@ module Pod end it 'uses a browser user-agent to validate URLs' do - WebMock::API.stub_request(:get, 'http://SOME-URL/foo'). + WebMock::API.stub_request(:head, /foo/).to_return(:status => 404) + WebMock::API.stub_request(:get, /foo/). with(:headers => { :user_agent => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10) AppleWebKit/538.43.40 (KHTML, like Gecko) Version/8.0 Safari/538.43.40' }). to_return(:status => 200, :body => '') response = HTTP.validate_url('http://SOME-URL/foo') response.success?.should.be.true end + + it 'uses GET with Range of 1 byte' do + WebMock::API.stub_request(:head, /foo/).to_return(:status => 404) + WebMock::API.stub_request(:get, /foo/). + with(:headers => { :range => 'bytes=0-0' }). + to_return(:status => 200, :body => ' ') + + response = HTTP.validate_url('http://SOME-URL/foo') + response.success?.should.be.true + end + + it 'uses GET without Range if server rejects Range' do + WebMock::API.stub_request(:head, /foo/).to_return(:status => 404) + WebMock::API.stub_request(:get, /foo/). + with(:headers => { :range => 'bytes=0-0' }). + to_return(:status => 500) + WebMock::API.stub_request(:get, /foo/). + with { |request| request.headers.nil? || !request.headers.key?('Range') }. + to_return(:status => 200, :body => '') + + response = HTTP.validate_url('http://SOME-URL/foo') + response.success?.should.be.true + end end #-------------------------------------------------------------------------#