diff options
Diffstat (limited to 'lib/rubygems/request')
| -rw-r--r-- | lib/rubygems/request/connection_pools.rb | 60 | ||||
| -rw-r--r-- | lib/rubygems/request/http_pool.rb | 22 | ||||
| -rw-r--r-- | lib/rubygems/request/https_pool.rb | 5 |
3 files changed, 50 insertions, 37 deletions
diff --git a/lib/rubygems/request/connection_pools.rb b/lib/rubygems/request/connection_pools.rb index 31fc609800..01e7e0629a 100644 --- a/lib/rubygems/request/connection_pools.rb +++ b/lib/rubygems/request/connection_pools.rb @@ -1,36 +1,35 @@ # frozen_string_literal: true -require 'thread' class Gem::Request::ConnectionPools # :nodoc: - - @client = Net::HTTP + @client = Gem::Net::HTTP class << self attr_accessor :client end - def initialize proxy_uri, cert_files + def initialize(proxy_uri, cert_files, pool_size = 1) @proxy_uri = proxy_uri @cert_files = cert_files @pools = {} - @pool_mutex = Mutex.new + @pool_mutex = Thread::Mutex.new + @pool_size = pool_size end - def pool_for uri + def pool_for(uri) http_args = net_http_args(uri, @proxy_uri) key = http_args + [https?(uri)] @pool_mutex.synchronize do @pools[key] ||= - if https? uri then - Gem::Request::HTTPSPool.new(http_args, @cert_files, @proxy_uri) + if https? uri + Gem::Request::HTTPSPool.new(http_args, @cert_files, @proxy_uri, @pool_size) else - Gem::Request::HTTPPool.new(http_args, @cert_files, @proxy_uri) + Gem::Request::HTTPPool.new(http_args, @cert_files, @proxy_uri, @pool_size) end end end def close_all - @pools.each_value {|pool| pool.close_all} + @pools.each_value(&:close_all) end private @@ -39,37 +38,48 @@ class Gem::Request::ConnectionPools # :nodoc: # Returns list of no_proxy entries (if any) from the environment def get_no_proxy_from_env - env_no_proxy = ENV['no_proxy'] || ENV['NO_PROXY'] + env_no_proxy = ENV["no_proxy"] || ENV["NO_PROXY"] - return [] if env_no_proxy.nil? or env_no_proxy.empty? + return [] if env_no_proxy.nil? || env_no_proxy.empty? env_no_proxy.split(/\s*,\s*/) end - def https? uri - uri.scheme.downcase == 'https' + def https?(uri) + uri.scheme.casecmp("https").zero? end - def no_proxy? host, env_no_proxy + def no_proxy?(host, env_no_proxy) host = host.downcase env_no_proxy.any? do |pattern| - pattern = pattern.downcase + env_no_proxy_pattern = pattern.downcase.dup + + # Remove dot in front of pattern for wildcard matching + env_no_proxy_pattern[0] = "" if env_no_proxy_pattern[0] == "." + + host_tokens = host.split(".") + pattern_tokens = env_no_proxy_pattern.split(".") + + intersection = (host_tokens - pattern_tokens) | (pattern_tokens - host_tokens) - host[-pattern.length, pattern.length] == pattern or - (pattern.start_with? '.' and pattern[1..-1] == host) + # When we do the split into tokens we miss a dot character, so add it back if we need it + missing_dot = intersection.length > 0 ? 1 : 0 + start = intersection.join(".").size + missing_dot + + no_proxy_host = host[start..-1] + + env_no_proxy_pattern == no_proxy_host end end - def net_http_args uri, proxy_uri - # URI::Generic#hostname was added in ruby 1.9.3, use it if exists, otherwise - # don't support IPv6 literals and use host. - hostname = uri.respond_to?(:hostname) ? uri.hostname : uri.host + def net_http_args(uri, proxy_uri) + hostname = uri.hostname net_http_args = [hostname, uri.port] no_proxy = get_no_proxy_from_env - if proxy_uri and not no_proxy?(hostname, no_proxy) then + if proxy_uri && !no_proxy?(hostname, no_proxy) proxy_hostname = proxy_uri.respond_to?(:hostname) ? proxy_uri.hostname : proxy_uri.host net_http_args + [ proxy_hostname, @@ -77,12 +87,10 @@ class Gem::Request::ConnectionPools # :nodoc: Gem::UriFormatter.new(proxy_uri.user).unescape, Gem::UriFormatter.new(proxy_uri.password).unescape, ] - elsif no_proxy? hostname, no_proxy then + elsif no_proxy? hostname, no_proxy net_http_args + [nil, nil] else net_http_args end end - end - diff --git a/lib/rubygems/request/http_pool.rb b/lib/rubygems/request/http_pool.rb index bfcd15399d..468502ca6b 100644 --- a/lib/rubygems/request/http_pool.rb +++ b/lib/rubygems/request/http_pool.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + ## # A connection "pool" that only manages one connection for now. Provides # thread safe `checkout` and `checkin` methods. The pool consists of one @@ -8,29 +9,32 @@ class Gem::Request::HTTPPool # :nodoc: attr_reader :cert_files, :proxy_uri - def initialize http_args, cert_files, proxy_uri + def initialize(http_args, cert_files, proxy_uri, pool_size) @http_args = http_args @cert_files = cert_files @proxy_uri = proxy_uri - @queue = SizedQueue.new 1 - @queue << nil + @pool_size = pool_size + + @queue = Thread::SizedQueue.new @pool_size + setup_queue end def checkout @queue.pop || make_connection end - def checkin connection + def checkin(connection) @queue.push connection end def close_all until @queue.empty? - if connection = @queue.pop(true) and connection.started? + if (connection = @queue.pop(true)) && connection.started? connection.finish end end - @queue.push(nil) + + setup_queue end private @@ -39,10 +43,12 @@ class Gem::Request::HTTPPool # :nodoc: setup_connection Gem::Request::ConnectionPools.client.new(*@http_args) end - def setup_connection connection + def setup_connection(connection) connection.start connection end + def setup_queue + @pool_size.times { @queue.push(nil) } + end end - diff --git a/lib/rubygems/request/https_pool.rb b/lib/rubygems/request/https_pool.rb index e82c2440e1..cb1d4b59b6 100644 --- a/lib/rubygems/request/https_pool.rb +++ b/lib/rubygems/request/https_pool.rb @@ -1,11 +1,10 @@ # frozen_string_literal: true + class Gem::Request::HTTPSPool < Gem::Request::HTTPPool # :nodoc: private - def setup_connection connection + def setup_connection(connection) Gem::Request.configure_connection_for_https(connection, @cert_files) super end end - - |
