lib/httpx/plugins/proxy.rb in httpx-0.22.5 vs lib/httpx/plugins/proxy.rb in httpx-0.23.0
- old
+ new
@@ -16,10 +16,47 @@
#
module Proxy
Error = HTTPProxyError
PROXY_ERRORS = [TimeoutError, IOError, SystemCallError, Error].freeze
+ class << self
+ def configure(klass)
+ klass.plugin(:"proxy/http")
+ klass.plugin(:"proxy/socks4")
+ klass.plugin(:"proxy/socks5")
+ end
+
+ if URI::Generic.methods.include?(:use_proxy?)
+ def use_proxy?(*args)
+ URI::Generic.use_proxy?(*args)
+ end
+ else
+ # https://github.com/ruby/uri/blob/ae07f956a4bea00b4f54a75bd40b8fa918103eed/lib/uri/generic.rb
+ def use_proxy?(hostname, addr, port, no_proxy)
+ hostname = hostname.downcase
+ dothostname = ".#{hostname}"
+ no_proxy.scan(/([^:,\s]+)(?::(\d+))?/) do |p_host, p_port|
+ if !p_port || port == p_port.to_i
+ if p_host.start_with?(".")
+ return false if hostname.end_with?(p_host.downcase)
+ else
+ return false if dothostname.end_with?(".#{p_host.downcase}")
+ end
+ if addr
+ begin
+ return false if IPAddr.new(p_host).include?(addr)
+ rescue IPAddr::InvalidAddressError
+ next
+ end
+ end
+ end
+ end
+ true
+ end
+ end
+ end
+
class Parameters
attr_reader :uri, :username, :password, :scheme
def initialize(uri:, scheme: nil, username: nil, password: nil, **extra)
@uri = uri.is_a?(URI::Generic) ? uri : URI(uri)
@@ -75,56 +112,53 @@
super
end
end
end
- class << self
- def configure(klass)
- klass.plugin(:"proxy/http")
- klass.plugin(:"proxy/socks4")
- klass.plugin(:"proxy/socks5")
- end
- end
-
module OptionsMethods
def option_proxy(value)
value.is_a?(Parameters) ? value : Hash[value]
end
end
module InstanceMethods
private
- def proxy_uris(uri, options)
- @_proxy_uris ||= begin
- uris = options.proxy ? Array(options.proxy[:uri]) : []
- if uris.empty?
- uri = URI(uri).find_proxy
- uris << uri if uri
- end
- uris
- end
- return if @_proxy_uris.empty?
+ def find_connection(request, connections, options)
+ return super unless options.respond_to?(:proxy)
- proxy = options.proxy
+ uri = URI(request.uri)
- return { uri: uri.host } if proxy && proxy.key?(:no_proxy) && !Array(proxy[:no_proxy]).grep(uri.host).empty?
+ proxy_opts = if (next_proxy = uri.find_proxy)
+ { uri: next_proxy }
+ else
+ proxy = options.proxy
- proxy_opts = { uri: @_proxy_uris.first }
- proxy_opts = options.proxy.merge(proxy_opts) if options.proxy
- proxy_opts
- end
+ return super unless proxy
- def find_connection(request, connections, options)
- return super unless options.respond_to?(:proxy)
+ return super(request, connections, options.merge(proxy: nil)) unless proxy.key?(:uri)
- uri = URI(request.uri)
- next_proxy = proxy_uris(uri, options)
- raise Error, "Failed to connect to proxy" unless next_proxy
+ @_proxy_uris ||= Array(proxy[:uri])
- proxy = Parameters.new(**next_proxy) unless next_proxy[:uri] == uri.host
+ next_proxy = @_proxy_uris.first
+ raise Error, "Failed to connect to proxy" unless next_proxy
+ if proxy.key?(:no_proxy)
+ next_proxy = URI(next_proxy)
+
+ no_proxy = proxy[:no_proxy]
+ no_proxy = no_proxy.join(",") if no_proxy.is_a?(Array)
+
+ return super(request, connections, options.merge(proxy: nil)) unless Proxy.use_proxy?(uri.host, next_proxy.host,
+ next_proxy.port, no_proxy)
+ end
+
+ proxy.merge(uri: next_proxy)
+ end
+
+ proxy = Parameters.new(**proxy_opts)
+
proxy_options = options.merge(proxy: proxy)
connection = pool.find_connection(uri, proxy_options) || build_connection(uri, proxy_options)
unless connections.nil? || connections.include?(connection)
connections << connection
set_connection_callbacks(connection, connections, options)
@@ -282,10 +316,10 @@
end
end
register_plugin :proxy, Proxy
end
- class ProxySSL < IO.registry["ssl"]
+ class ProxySSL < SSL
def initialize(tcp, request_uri, options)
@io = tcp.to_io
super(request_uri, tcp.addresses, options)
@hostname = request_uri.host
@state = :connected