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