Skip to content

Commit

Permalink
Support no_proxy via URI::Generic#find_proxy (#670)
Browse files Browse the repository at this point in the history
* Revert "Implement no_proxy feature (#658)"

This reverts commit dea7726.

Conflicts:
	lib/faraday/options.rb

* Support no_proxy via URI::Generic#find_proxy

* remove `return`

* reintroduce all tests from 511a5b4
  • Loading branch information
authorNari authored and iMacTia committed Mar 15, 2017
1 parent 565b2a4 commit 3268aca
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 112 deletions.
67 changes: 27 additions & 40 deletions lib/faraday/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,22 @@ def initialize(url = nil, options = nil)
@params.update(options.params) if options.params
@headers.update(options.headers) if options.headers

@proxy = @no_proxy = nil
@proxy = nil
proxy(options.fetch(:proxy) {
uri = ENV['http_proxy']
if uri && !uri.empty?
uri = 'http://' + uri unless uri.downcase.start_with?('http')
uri
uri = nil
if URI.parse("").respond_to?(:find_proxy)
case url
when String
uri = URI.parse(url).find_proxy
when URI
uri = url.find_proxy
when nil
uri = find_default_proxy
end
else
uri = find_default_proxy
end
}, options.fetch(:no_proxy) {
ENV['no_proxy']
uri
})

yield(self) if block_given?
Expand Down Expand Up @@ -283,12 +290,9 @@ def in_parallel(manager = nil)
end

# Public: Gets or Sets the Hash proxy options.
def proxy(proxy = nil, no_proxy = nil)
return @proxy if proxy.nil?
@no_proxy = no_proxy
.scan(/(?!\.)([^:,\s]+)(?::(\d+))?/)
.map {|host, port| [host, port, /(\A|\.)#{Regexp.quote host}\z/i]} unless no_proxy.nil?
@proxy = ProxyOptions.from(proxy)
def proxy(arg = nil)
return @proxy if arg.nil?
@proxy = ProxyOptions.from(arg)
end

def_delegators :url_prefix, :scheme, :scheme=, :host, :host=, :port, :port=
Expand Down Expand Up @@ -376,7 +380,6 @@ def run_request(method, url, body, headers)
req.url(url) if url
req.headers.update(headers) if headers
req.body = body if body
req.options.merge!(:proxy => self.proxy) if proxy_allowed?(build_exclusive_url(req.path))
yield(req) if block_given?
end

Expand All @@ -390,36 +393,11 @@ def build_request(method)
Request.create(method) do |req|
req.params = self.params.dup
req.headers = self.headers.dup
req.options = self.options
req.options = self.options.merge(:proxy => self.proxy)
yield(req) if block_given?
end
end

def proxy_allowed?(url)
return true if @no_proxy.nil?
uri = Utils.URI(url)
@no_proxy.none? do |host, port, host_regex|
next false if (port && uri.port != port.to_i)
next true if host_regex =~ uri.host
if uri.hostname
require 'socket'
begin
addr = IPSocket.getaddress(uri.hostname)
next true if /\A127\.|\A::1\z/ =~ addr
rescue SocketError
end
next false unless addr
require 'ipaddr'
next true if
begin
IPAddr.new(host)
rescue
next false
end.include?(addr)
end
end
end

# Internal: Build an absolute URL based on url_prefix.
#
# url - A String or URI-like object
Expand Down Expand Up @@ -464,5 +442,14 @@ def set_authorization_header(header_type, *args)
header(*args)
headers[Faraday::Request::Authorization::KEY] = header
end

def find_default_proxy
warn 'no_proxy is unsupported' if ENV['no_proxy'] || ENV['NO_PROXY']
uri = ENV['http_proxy']
if uri && !uri.empty?
uri = 'http://' + uri if uri !~ /^http/i
uri
end
end
end
end
2 changes: 1 addition & 1 deletion lib/faraday/options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ def self.from(value)
memoized(:password) { uri.password && Utils.unescape(uri.password) }
end

class ConnectionOptions < Options.new(:request, :ssl, :proxy, :no_proxy, :builder, :url,
class ConnectionOptions < Options.new(:request, :proxy, :ssl, :builder, :url,
:parallel_manager, :params, :headers, :builder_class)

options :request => RequestOptions, :ssl => SSLOptions
Expand Down
9 changes: 0 additions & 9 deletions test/adapters/integration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -204,15 +204,6 @@ def test_proxy
end
end

def test_no_proxy
proxy_uri = URI(ENV['LIVE_PROXY'])
conn = create_connection(:proxy => proxy_uri, :no_proxy => 'localhost')

res = conn.get '/echo'

assert_nil res['via']
end

def test_proxy_auth_fail
proxy_uri = URI(ENV['LIVE_PROXY'])
proxy_uri.password = 'WRONG'
Expand Down
104 changes: 42 additions & 62 deletions test/connection_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -369,83 +369,63 @@ def test_proxy_doesnt_accept_uppercase_env
end
end

def test_proxy_requires_uri
conn = Faraday::Connection.new
assert_raises ArgumentError do
conn.proxy :uri => :bad_uri, :user => 'rick'
end
end

def test_proxy_allowed_when_url_in_no_proxy_list
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example.com' do
conn = Faraday::Connection.new
assert_equal conn.proxy_allowed?('http://example.com'), false
end
end

def test_proxy_allowed_when_prefixed_url_is_not_in_no_proxy_list
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example.com' do
conn = Faraday::Connection.new
assert_equal conn.proxy_allowed?('http://prefixedexample.com'), true
end
end

def test_proxy_allowed_when_subdomain_url_is_in_no_proxy_list
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example.com' do
conn = Faraday::Connection.new
assert_equal conn.proxy_allowed?('http://subdomain.example.com'), false
if URI.parse("").respond_to?(:find_proxy)
def test_proxy_allowed_when_url_in_no_proxy_list
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example.com' do
conn = Faraday::Connection.new('http://example.com')
assert_nil conn.proxy
end
end
end

def test_proxy_allowed_when_url_not_in_no_proxy_list
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example2.com' do
conn = Faraday::Connection.new
assert_equal conn.proxy_allowed?('http://example.com'), true
def test_proxy_allowed_when_prefixed_url_is_not_in_no_proxy_list
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example.com' do
conn = Faraday::Connection.new('http://prefixedexample.com')
assert_equal 'proxy.com', conn.proxy.host
end
end
end

def test_proxy_allowed_when_ip_address_is_not_in_no_proxy_list_but_url_is
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'localhost' do
conn = Faraday::Connection.new
assert_equal conn.proxy_allowed?('http://127.0.0.1'), false
def test_proxy_allowed_when_subdomain_url_is_in_no_proxy_list
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example.com' do
conn = Faraday::Connection.new('http://subdomain.example.com')
assert_nil conn.proxy
end
end
end

def test_proxy_allowed_when_url_is_not_in_no_proxy_list_but_ip_address_is
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => '127.0.0.1' do
conn = Faraday::Connection.new
assert_equal conn.proxy_allowed?('http://localhost'), false
def test_proxy_allowed_when_url_not_in_no_proxy_list
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example2.com' do
conn = Faraday::Connection.new('http://example.com')
assert_equal 'proxy.com', conn.proxy.host
end
end
end

def test_proxy_allowed_in_multi_element_no_proxy_list
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example0.com,example.com,example1.com' do
conn = Faraday::Connection.new
assert_equal conn.proxy_allowed?('http://example0.com'), false
assert_equal conn.proxy_allowed?('http://example.com'), false
assert_equal conn.proxy_allowed?('http://example1.com'), false
assert_equal conn.proxy_allowed?('http://example2.com'), true
def test_proxy_allowed_when_ip_address_is_not_in_no_proxy_list_but_url_is
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'localhost' do
conn = Faraday::Connection.new('http://127.0.0.1')
assert_nil conn.proxy
end
end
end

def test_proxy_allowed_when_ports_match_in_no_proxy_list
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example.com:7171' do
conn = Faraday::Connection.new
assert_equal conn.proxy_allowed?('http://example.com:7171'), false
def test_proxy_allowed_when_url_is_not_in_no_proxy_list_but_ip_address_is
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => '127.0.0.1' do
conn = Faraday::Connection.new('http://localhost')
assert_nil conn.proxy
end
end
end

def test_proxy_allowed_when_port_is_not_set_in_no_proxy_list
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example.com' do
conn = Faraday::Connection.new
assert_equal conn.proxy_allowed?('http://example.com:7171'), false
def test_proxy_allowed_in_multi_element_no_proxy_list
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example0.com,example.com,example1.com' do
assert_nil Faraday::Connection.new('http://example0.com').proxy
assert_nil Faraday::Connection.new('http://example.com').proxy
assert_nil Faraday::Connection.new('http://example1.com').proxy
assert_equal 'proxy.com', Faraday::Connection.new('http://example2.com').proxy.host
end
end
end

def test_proxy_allowed_when_ports_mismatch_in_no_proxy_list
with_env 'http_proxy' => 'http://proxy.com', 'no_proxy' => 'example.com:3000' do
conn = Faraday::Connection.new
assert_equal conn.proxy_allowed?('http://example.com:7171'), true
def test_proxy_requires_uri
conn = Faraday::Connection.new
assert_raises ArgumentError do
conn.proxy :uri => :bad_uri, :user => 'rick'
end
end

Expand Down
5 changes: 5 additions & 0 deletions test/env_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ def test_request_create_stores_ssl_options
assert_equal false, env.ssl.verify
end

def test_request_create_stores_proxy_options
env = make_env
assert_equal 'proxy.com', env.request.proxy.host
end

def test_custom_members_are_retained
env = make_env
env[:foo] = "custom 1"
Expand Down

0 comments on commit 3268aca

Please sign in to comment.