summaryrefslogtreecommitdiff
path: root/lib/rubygems/request
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rubygems/request')
-rw-r--r--lib/rubygems/request/connection_pools.rb60
-rw-r--r--lib/rubygems/request/http_pool.rb22
-rw-r--r--lib/rubygems/request/https_pool.rb5
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
-
-