diff --git a/lib/uri/generic.rb b/lib/uri/generic.rb index 6a0f638..e90332a 100644 --- a/lib/uri/generic.rb +++ b/lib/uri/generic.rb @@ -1552,18 +1552,22 @@ def find_proxy(env=ENV) return nil end + name = 'no_proxy' + no_proxy = env[name] || env[name.upcase] if self.hostname + if no_proxy && !URI::Generic.use_proxy?(self.hostname, nil, self.port, no_proxy) + return nil + end + begin addr = IPSocket.getaddress(self.hostname) return nil if /\A127\.|\A::1\z/ =~ addr rescue SocketError end - end - name = 'no_proxy' - if no_proxy = env[name] || env[name.upcase] - return nil unless URI::Generic.use_proxy?(self.hostname, addr, self.port, no_proxy) + return nil if no_proxy && !URI::Generic.use_proxy?(self.hostname, addr, self.port, no_proxy) end + URI.parse(proxy_uri) end diff --git a/test/uri/test_generic.rb b/test/uri/test_generic.rb index 94eea71..e221925 100644 --- a/test/uri/test_generic.rb +++ b/test/uri/test_generic.rb @@ -972,6 +972,37 @@ def test_find_proxy_no_proxy end end + def test_find_proxy_no_proxy_not_resolving_hostname + getaddress = IPSocket.method(:getaddress) + resolved_hosts = [] + IPSocket.singleton_class.class_eval do + undef getaddress + define_method(:getaddress) do |host| + resolved_hosts << host + host + end + end + + with_proxy_env('http_proxy'=>'http://127.0.0.1:8080', 'no_proxy'=>'example.org') {|env| + assert_nil(URI("http://example.org/").find_proxy(env)) + assert_nil(URI("http://www.example.org/").find_proxy(env)) + } + with_proxy_env('http_proxy'=>'http://127.0.0.1:8080', 'no_proxy'=>'.example.org') {|env| + assert_nil(URI("http://www.example.org/").find_proxy(env)) + } + with_proxy_env('http_proxy'=>'http://127.0.0.1:8080', 'no_proxy'=>'192.0.2.2') {|env| + assert_nil(URI("http://192.0.2.2/").find_proxy(env)) + } + + assert_equal([], resolved_hosts, + "IPSocket.getaddress should not be called when hostname matches no_proxy") + ensure + IPSocket.singleton_class.class_eval do + undef getaddress + define_method(:getaddress, getaddress) + end + end + def test_find_proxy_no_proxy_cidr with_proxy_env('http_proxy'=>'http://127.0.0.1:8080', 'no_proxy'=>'192.0.2.0/24') {|env| assert_equal(URI('http://127.0.0.1:8080'), URI("http://192.0.1.1/").find_proxy(env))