メタデータの取得は*_proxy環境変数を見るのみなのだが、gemのダウンロードはrubygemを利用していているので、環境変数だけでなく.gemrcのhttp_proxyの設定を見てしまう。さらに、.gemrcの方を優先してしまう。
そのため、.gemrcに間違った設定を入れていると環境変数の方に正しい設定をしていても、メタデータのみ取得してgemは取得できないというようなことになってしまう。
例えば、proxyのない環境で.gemrcに
http_proxy: http://hogehoge:8080
と存在しないproxyの設定をして、bundle installを実行すると
$ bundle install Fetching gem metadata from https://rubygems.org/........... Fetching version metadata from https://rubygems.org/... Fetching dependency metadata from https://rubygems.org/.. Using rake 10.4.2
とうまくいっているように見えて、gemをインストールする段階になると以下のようなエラーになる。
Gem::RemoteFetcher::UnknownHostError: no such name (https://rubygems.org/gems/faker-1.1.2.gem) An error occurred while installing faker (1.1.2), and Bundler cannot continue. Make sure that `gem install faker -v '1.1.2'` succeeds before bundling.
コード的にはだいたいこんな感じ。(Bundler v1.10.0)
メタデータの取得時にはlib/bundler/fetcher.rbのfetch_specメソッドの中で、
def fetch_spec(spec) spec = spec - [nil, 'ruby', ''] spec_file_name = "#{spec.join '-'}.gemspec" uri = URI.parse("#{remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz") if uri.scheme == 'file' Bundler.load_marshal Gem.inflate(Gem.read_binary(uri.path)) elsif cached_spec_path = gemspec_cached_path(spec_file_name) Bundler.load_gemspec(cached_spec_path) else Bundler.load_marshal Gem.inflate(downloader.fetch uri) end rescue MarshalError raise HTTPError, "Gemspec #{spec} contained invalid data.\n" \ "Your network or your gem server is probably having issues right now." end
downloader.fetchして、lib/bundler/fetcher/downloader.rbのfetchメソッドの中で
def fetch(uri, counter = 0) raise HTTPError, "Too many redirects" if counter >= redirect_limit response = request(uri)
def request(uri) Bundler.ui.debug "HTTP GET #{uri}" req = Net::HTTP::Get.new uri.request_uri
Net::HTTPを利用しているので*_proxy環境変数を見ることになる。
gemのインストールの場合はlib/bundler/rubygems_integration.rbのdownload_gemメソッドの中で
def download_gem(spec, uri, path) uri = Bundler.settings.mirror_for(uri) fetcher = Gem::RemoteFetcher.new(configuration[:http_proxy]) fetcher.download(spec, uri, path) end
configuration[:http_proxy]を引数にGem::RemoteFetcherを生成している。configurationはgemの設定ファイル(.gemrc)であり、Gem::RemoteFetcherのコンストラクタは引数としてproxyをとり、*_proxy環境変数より優先させる。