Skip to content

Commit

Permalink
[Http] add default User-Agent string to cURL requests, unless one is …
Browse files Browse the repository at this point in the history
…provided by :headers
  • Loading branch information
seanreinhardtapps committed Jun 7, 2020
1 parent ac033ad commit 8179b8f
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 1 deletion.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

##### Enhancements

* None.
* Add User-Agent to `cURL` requests when downloading source via the `:http` download strategy, unless one was provided by the `:headers` option.
[Sean Reinhardt](https://github.com/seanreinhardtapps)
[#9619](https://github.com/CocoaPods/CocoaPods/issues/9619)

##### Bug Fixes

Expand Down
12 changes: 12 additions & 0 deletions lib/cocoapods-downloader/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,18 @@ def checkout_options
raise 'Abstract method'
end

# Returns a User-Agent string that itentifies http network requests as
# originating from CocoaPods.
# Contains version numbers from the CocoaPods Gem and the cocoapods-downloader Gem.
#
# @param [module] base_module The Base CocoaPods Module to retrieve the version number from.
# @return [String] the User-Agent string.
#
def self.user_agent_string(base_module = Pod)
pods_version = base_module.const_defined?('VERSION') ? "CocoaPods/#{base_module::VERSION} " : ''
"#{pods_version}cocoapods-downloader/#{Pod::Downloader::VERSION}"
end

#-----------------------------------------------------------------------#

# Defines two methods for an executable, based on its name. The bang
Expand Down
12 changes: 12 additions & 0 deletions lib/cocoapods-downloader/http.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
module Pod
module Downloader
class Http < RemoteFile
USER_AGENT_HEADER = 'User-Agent'.freeze

private

executable :curl

def download_file(full_filename)
parameters = ['-f', '-L', '-o', full_filename, url, '--create-dirs', '--netrc-optional', '--retry', '2']
parameters << user_agent_argument if headers.nil? ||
headers.none? { |header| header.casecmp(USER_AGENT_HEADER).zero? }

headers.each do |h|
parameters << '-H'
Expand All @@ -17,6 +21,14 @@ def download_file(full_filename)

curl! parameters
end

# Returns a cURL command flag to add the CocoaPods User-Agent.
#
# @return [String] cURL command -A flag and User-Agent.
#
def user_agent_argument
"-A '#{Http.user_agent_string}'"
end
end
end
end
14 changes: 14 additions & 0 deletions spec/base_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,20 @@ module Downloader
new_options = Base.preprocess_options(options)
new_options.should == options
end

it 'defines a user agent with the cocoapods-downloader version' do
module TestModuleNoVersion
end
Base.user_agent_string(TestModuleNoVersion).should == "cocoapods-downloader/#{Pod::Downloader::VERSION}"
end

it 'defines a user agent containing CocoaPods downloader versions when available' do
module TestModuleWithVersion
VERSION = 'a.b.c'.freeze
end
Base.user_agent_string(TestModuleWithVersion).should ==
"CocoaPods/#{TestModuleWithVersion::VERSION} cocoapods-downloader/#{Pod::Downloader::VERSION}"
end
end
end
end
74 changes: 74 additions & 0 deletions spec/http_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
module Pod
module Downloader
describe 'HTTP' do
mock_user_agent = 'mock_user_agent'.freeze
before do
tmp_folder.rmtree if tmp_folder.exist?
@fixtures_url = 'file://' + fixture('http').to_s
Http.stubs(:user_agent_string).returns(mock_user_agent)
end

it 'download file and unzip it' do
Expand Down Expand Up @@ -75,6 +77,78 @@ module Downloader
downloader.download
end
end

it 'passes User-Agent to cURL' do
options = { :http => "#{@fixtures_url}/lib.zip" }
downloader = Downloader.for_target(tmp_folder, options)
downloader.expects(:curl!).with(
includes("-A \'#{mock_user_agent}\'"),
)
should.raise DownloaderError do
downloader.download
end
end

it 'passes default User-Agent to cURL with other request headers' do
options = { :http => "#{@fixtures_url}/lib.zip",
:headers => ['Accept: application/json'],
}
downloader = Downloader.for_target(tmp_folder, options)
downloader.expects(:curl!).with(
includes("-A \'#{mock_user_agent}\'"),
)
should.raise DownloaderError do
downloader.download
end
end

it 'prefers User-Agent provided in headers over default User-Agent' do
options = {
:http => "#{@fixtures_url}/lib.zip",
:headers => ['Accept: application/json', 'User-Agent: custom_user_agent'],
}
downloader = Downloader.for_target(tmp_folder, options)
downloader.expects(:curl!).with(
all_of(
includes('-H'),
includes('Accept: application/json'),
includes('-H'),
includes('User-Agent: custom_user_agent'),
),
Not(
includes("-A \'#{mock_user_agent}\'"),
),
)
should.raise DownloaderError do
downloader.download
end
end

it 'prefers case insensitive User-Agent provided in headers' do
options = {
:http => "#{@fixtures_url}/lib.zip",
:headers => ['Accept: application/json', 'user-agent: custom_user_agent'],
}
downloader = Downloader.for_target(tmp_folder, options)
downloader.expects(:curl!).with(
all_of(
includes('-H'),
includes('Accept: application/json'),
includes('-H'),
includes('user-agent: custom_user_agent'),
),
Not(
includes("-A \'#{mock_user_agent}\'"),
),
)
should.raise DownloaderError do
downloader.download
end
end

it 'supplies User-Agent argument for cURL' do
Http.new('', '', {}).instance_eval { user_agent_argument }.should.match /-A '#{mock_user_agent}'/
end
end
end
end
1 change: 1 addition & 0 deletions spec/remote_file_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ def download_file(full_filename)
before do
tmp_folder.rmtree if tmp_folder.exist?
@fixtures_url = 'file://' + fixture('remote_file').to_s
RemoteFile.stubs(:user_agent_string).returns('mock_user_agent')
end

it 'download file and unzip it' do
Expand Down

0 comments on commit 8179b8f

Please sign in to comment.