Skip to content

Commit

Permalink
Add Range header to HTTP::perform_head_request
Browse files Browse the repository at this point in the history
Uses a GET request with a 1 byte Range header if the initial HEAD request fails. Falls back to a GET request without a Range header if that also fails.
  • Loading branch information
kylefleming committed Jan 25, 2018
1 parent 98031f0 commit 5c700e2
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 4 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
9 changes: 7 additions & 2 deletions lib/cocoapods-core/http.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Expand Down
32 changes: 30 additions & 2 deletions spec/http_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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)

Expand All @@ -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

#-------------------------------------------------------------------------#
Expand Down

0 comments on commit 5c700e2

Please sign in to comment.