2016-02-01 07:43:26 -05:00
|
|
|
# frozen_string_literal: true
|
2014-09-13 23:30:02 -04:00
|
|
|
|
|
|
|
class Gem::Request::ConnectionPools # :nodoc:
|
|
|
|
|
|
|
|
@client = Net::HTTP
|
|
|
|
|
|
|
|
class << self
|
2019-02-14 07:59:03 -05:00
|
|
|
|
2014-09-13 23:30:02 -04:00
|
|
|
attr_accessor :client
|
2019-02-14 07:59:03 -05:00
|
|
|
|
2014-09-13 23:30:02 -04:00
|
|
|
end
|
|
|
|
|
2018-11-21 05:20:47 -05:00
|
|
|
def initialize(proxy_uri, cert_files)
|
2014-09-13 23:30:02 -04:00
|
|
|
@proxy_uri = proxy_uri
|
|
|
|
@cert_files = cert_files
|
|
|
|
@pools = {}
|
|
|
|
@pool_mutex = Mutex.new
|
|
|
|
end
|
|
|
|
|
2018-11-21 05:20:47 -05:00
|
|
|
def pool_for(uri)
|
2014-09-13 23:30:02 -04:00
|
|
|
http_args = net_http_args(uri, @proxy_uri)
|
|
|
|
key = http_args + [https?(uri)]
|
|
|
|
@pool_mutex.synchronize do
|
|
|
|
@pools[key] ||=
|
2018-11-21 05:20:47 -05:00
|
|
|
if https? uri
|
2014-09-13 23:30:02 -04:00
|
|
|
Gem::Request::HTTPSPool.new(http_args, @cert_files, @proxy_uri)
|
|
|
|
else
|
|
|
|
Gem::Request::HTTPPool.new(http_args, @cert_files, @proxy_uri)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-11-16 22:55:02 -05:00
|
|
|
def close_all
|
|
|
|
@pools.each_value {|pool| pool.close_all}
|
|
|
|
end
|
|
|
|
|
2014-09-13 23:30:02 -04:00
|
|
|
private
|
|
|
|
|
|
|
|
##
|
|
|
|
# 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']
|
|
|
|
|
2019-02-14 07:59:03 -05:00
|
|
|
return [] if env_no_proxy.nil? or env_no_proxy.empty?
|
2014-09-13 23:30:02 -04:00
|
|
|
|
|
|
|
env_no_proxy.split(/\s*,\s*/)
|
|
|
|
end
|
|
|
|
|
2018-11-21 05:20:47 -05:00
|
|
|
def https?(uri)
|
2014-09-13 23:30:02 -04:00
|
|
|
uri.scheme.downcase == 'https'
|
|
|
|
end
|
|
|
|
|
2018-11-21 05:20:47 -05:00
|
|
|
def no_proxy?(host, env_no_proxy)
|
2014-09-13 23:30:02 -04:00
|
|
|
host = host.downcase
|
|
|
|
|
|
|
|
env_no_proxy.any? do |pattern|
|
2018-05-30 09:01:35 -04:00
|
|
|
env_no_proxy_pattern = pattern.downcase.dup
|
2014-09-13 23:30:02 -04:00
|
|
|
|
2018-05-30 09:01:35 -04:00
|
|
|
# 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)
|
|
|
|
|
|
|
|
# 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
|
2014-09-13 23:30:02 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-11-21 05:20:47 -05:00
|
|
|
def net_http_args(uri, proxy_uri)
|
2015-07-01 17:50:14 -04:00
|
|
|
# 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
|
|
|
|
net_http_args = [hostname, uri.port]
|
2014-09-13 23:30:02 -04:00
|
|
|
|
|
|
|
no_proxy = get_no_proxy_from_env
|
|
|
|
|
2018-11-21 05:20:47 -05:00
|
|
|
if proxy_uri and not no_proxy?(hostname, no_proxy)
|
2015-07-01 17:50:14 -04:00
|
|
|
proxy_hostname = proxy_uri.respond_to?(:hostname) ? proxy_uri.hostname : proxy_uri.host
|
2014-09-13 23:30:02 -04:00
|
|
|
net_http_args + [
|
2015-07-01 17:50:14 -04:00
|
|
|
proxy_hostname,
|
2014-09-13 23:30:02 -04:00
|
|
|
proxy_uri.port,
|
|
|
|
Gem::UriFormatter.new(proxy_uri.user).unescape,
|
|
|
|
Gem::UriFormatter.new(proxy_uri.password).unescape,
|
|
|
|
]
|
2018-11-21 05:20:47 -05:00
|
|
|
elsif no_proxy? hostname, no_proxy
|
2014-11-16 22:55:02 -05:00
|
|
|
net_http_args + [nil, nil]
|
2014-09-13 23:30:02 -04:00
|
|
|
else
|
|
|
|
net_http_args
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|