faraday 0.11.0 → 0.17.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +232 -0
  3. data/LICENSE.md +1 -1
  4. data/README.md +151 -13
  5. data/Rakefile +13 -0
  6. data/lib/faraday/adapter/em_http.rb +9 -9
  7. data/lib/faraday/adapter/em_synchrony.rb +5 -5
  8. data/lib/faraday/adapter/excon.rb +6 -4
  9. data/lib/faraday/adapter/httpclient.rb +5 -5
  10. data/lib/faraday/adapter/net_http.rb +27 -9
  11. data/lib/faraday/adapter/net_http_persistent.rb +34 -16
  12. data/lib/faraday/adapter/patron.rb +32 -13
  13. data/lib/faraday/adapter/rack.rb +1 -1
  14. data/lib/faraday/adapter/test.rb +21 -13
  15. data/lib/faraday/adapter/typhoeus.rb +4 -115
  16. data/lib/faraday/adapter.rb +2 -0
  17. data/lib/faraday/autoload.rb +1 -1
  18. data/lib/faraday/connection.rb +59 -12
  19. data/lib/faraday/deprecate.rb +109 -0
  20. data/lib/faraday/error.rb +130 -35
  21. data/lib/faraday/options.rb +31 -25
  22. data/lib/faraday/parameters.rb +2 -1
  23. data/lib/faraday/rack_builder.rb +26 -2
  24. data/lib/faraday/request/multipart.rb +7 -2
  25. data/lib/faraday/request/retry.rb +76 -17
  26. data/lib/faraday/request.rb +20 -0
  27. data/lib/faraday/response/logger.rb +3 -3
  28. data/lib/faraday/response/raise_error.rb +7 -3
  29. data/lib/faraday/response.rb +3 -3
  30. data/lib/faraday/utils.rb +18 -9
  31. data/lib/faraday.rb +9 -5
  32. data/spec/faraday/deprecate_spec.rb +147 -0
  33. data/spec/faraday/error_spec.rb +102 -0
  34. data/spec/faraday/response/raise_error_spec.rb +106 -0
  35. data/spec/spec_helper.rb +105 -0
  36. data/test/adapters/default_test.rb +14 -0
  37. data/test/adapters/em_http_test.rb +30 -0
  38. data/test/adapters/em_synchrony_test.rb +32 -0
  39. data/test/adapters/excon_test.rb +30 -0
  40. data/test/adapters/httpclient_test.rb +34 -0
  41. data/test/adapters/integration.rb +263 -0
  42. data/test/adapters/logger_test.rb +136 -0
  43. data/test/adapters/net_http_persistent_test.rb +114 -0
  44. data/test/adapters/net_http_test.rb +79 -0
  45. data/test/adapters/patron_test.rb +40 -0
  46. data/test/adapters/rack_test.rb +38 -0
  47. data/test/adapters/test_middleware_test.rb +157 -0
  48. data/test/adapters/typhoeus_test.rb +38 -0
  49. data/test/authentication_middleware_test.rb +65 -0
  50. data/test/composite_read_io_test.rb +109 -0
  51. data/test/connection_test.rb +738 -0
  52. data/test/env_test.rb +268 -0
  53. data/test/helper.rb +75 -0
  54. data/test/live_server.rb +67 -0
  55. data/test/middleware/instrumentation_test.rb +88 -0
  56. data/test/middleware/retry_test.rb +282 -0
  57. data/test/middleware_stack_test.rb +260 -0
  58. data/test/multibyte.txt +1 -0
  59. data/test/options_test.rb +333 -0
  60. data/test/parameters_test.rb +157 -0
  61. data/test/request_middleware_test.rb +126 -0
  62. data/test/response_middleware_test.rb +72 -0
  63. data/test/strawberry.rb +2 -0
  64. data/test/utils_test.rb +98 -0
  65. metadata +48 -7
@@ -11,6 +11,7 @@ module Faraday
11
11
  class NetHttp < Faraday::Adapter
12
12
  NET_HTTP_EXCEPTIONS = [
13
13
  IOError,
14
+ Errno::EADDRNOTAVAIL,
14
15
  Errno::ECONNABORTED,
15
16
  Errno::ECONNREFUSED,
16
17
  Errno::ECONNRESET,
@@ -28,6 +29,11 @@ module Faraday
28
29
  NET_HTTP_EXCEPTIONS << OpenSSL::SSL::SSLError if defined?(OpenSSL)
29
30
  NET_HTTP_EXCEPTIONS << Net::OpenTimeout if defined?(Net::OpenTimeout)
30
31
 
32
+ def initialize(app = nil, opts = {}, &block)
33
+ @cert_store = nil
34
+ super(app, opts, &block)
35
+ end
36
+
31
37
  def call(env)
32
38
  super
33
39
  with_net_http_connection(env) do |http|
@@ -40,7 +46,7 @@ module Faraday
40
46
  if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err
41
47
  raise Faraday::SSLError, err
42
48
  else
43
- raise Error::ConnectionFailed, err
49
+ raise Faraday::ConnectionFailed, err
44
50
  end
45
51
  end
46
52
 
@@ -53,9 +59,11 @@ module Faraday
53
59
 
54
60
  @app.call env
55
61
  rescue Timeout::Error, Errno::ETIMEDOUT => err
56
- raise Faraday::Error::TimeoutError, err
62
+ raise Faraday::TimeoutError, err
57
63
  end
58
64
 
65
+ private
66
+
59
67
  def create_request(env)
60
68
  request = Net::HTTPGenericRequest.new \
61
69
  env[:method].to_s.upcase, # request method
@@ -87,10 +95,10 @@ module Faraday
87
95
 
88
96
  def net_http_connection(env)
89
97
  if proxy = env[:request][:proxy]
90
- Net::HTTP::Proxy(proxy[:uri].host, proxy[:uri].port, proxy[:user], proxy[:password])
98
+ Net::HTTP::Proxy(proxy[:uri].hostname, proxy[:uri].port, proxy[:user], proxy[:password])
91
99
  else
92
100
  Net::HTTP
93
- end.new(env[:url].host, env[:url].port || (env[:url].scheme == 'https' ? 443 : 80))
101
+ end.new(env[:url].hostname, env[:url].port || (env[:url].scheme == 'https' ? 443 : 80))
94
102
  end
95
103
 
96
104
  def configure_ssl(http, ssl)
@@ -104,21 +112,31 @@ module Faraday
104
112
  http.ca_path = ssl[:ca_path] if ssl[:ca_path]
105
113
  http.verify_depth = ssl[:verify_depth] if ssl[:verify_depth]
106
114
  http.ssl_version = ssl[:version] if ssl[:version]
115
+ http.min_version = ssl[:min_version] if ssl[:min_version]
116
+ http.max_version = ssl[:max_version] if ssl[:max_version]
107
117
  end
108
118
 
109
119
  def configure_request(http, req)
110
- http.read_timeout = http.open_timeout = req[:timeout] if req[:timeout]
111
- http.open_timeout = req[:open_timeout] if req[:open_timeout]
120
+ if req[:timeout]
121
+ http.read_timeout = req[:timeout]
122
+ http.open_timeout = req[:timeout]
123
+ http.write_timeout = req[:timeout] if http.respond_to?(:write_timeout=)
124
+ end
125
+ http.open_timeout = req[:open_timeout] if req[:open_timeout]
126
+ http.write_timeout = req[:write_timeout] if req[:write_timeout] && http.respond_to?(:write_timeout=)
127
+ # Only set if Net::Http supports it, since Ruby 2.5.
128
+ http.max_retries = 0 if http.respond_to?(:max_retries=)
112
129
 
113
130
  @config_block.call(http) if @config_block
114
131
  end
115
132
 
116
133
  def ssl_cert_store(ssl)
117
134
  return ssl[:cert_store] if ssl[:cert_store]
135
+ return @cert_store if @cert_store
118
136
  # Use the default cert store by default, i.e. system ca certs
119
- cert_store = OpenSSL::X509::Store.new
120
- cert_store.set_default_paths
121
- cert_store
137
+ @cert_store = OpenSSL::X509::Store.new
138
+ @cert_store.set_default_paths
139
+ @cert_store
122
140
  end
123
141
 
124
142
  def ssl_verify_mode(ssl)
@@ -1,13 +1,27 @@
1
- # Rely on autoloading instead of explicit require; helps avoid the "already
2
- # initialized constant" warning on Ruby 1.8.7 when NetHttp is refereced below.
3
- # require 'faraday/adapter/net_http'
4
-
5
1
  module Faraday
6
2
  class Adapter
7
3
  class NetHttpPersistent < NetHttp
8
4
  dependency 'net/http/persistent'
9
5
 
6
+ private
7
+
10
8
  def net_http_connection(env)
9
+ @cached_connection ||=
10
+ if Net::HTTP::Persistent.instance_method(:initialize).parameters.first == [:key, :name]
11
+ options = {name: 'Faraday'}
12
+ options[:pool_size] = @connection_options[:pool_size] if @connection_options.key?(:pool_size)
13
+ Net::HTTP::Persistent.new(**options)
14
+ else
15
+ Net::HTTP::Persistent.new('Faraday')
16
+ end
17
+
18
+ proxy_uri = proxy_uri(env)
19
+ @cached_connection.proxy = proxy_uri if @cached_connection.proxy_uri != proxy_uri
20
+ @cached_connection
21
+ end
22
+
23
+ def proxy_uri(env)
24
+ proxy_uri = nil
11
25
  if (proxy = env[:request][:proxy])
12
26
  proxy_uri = ::URI::HTTP === proxy[:uri] ? proxy[:uri].dup : ::URI.parse(proxy[:uri].to_s)
13
27
  proxy_uri.user = proxy_uri.password = nil
@@ -16,34 +30,38 @@ module Faraday
16
30
  define_method(:user) { proxy[:user] }
17
31
  define_method(:password) { proxy[:password] }
18
32
  end if proxy[:user]
19
- return Net::HTTP::Persistent.new 'Faraday', proxy_uri
20
33
  end
21
-
22
- Net::HTTP::Persistent.new 'Faraday'
34
+ proxy_uri
23
35
  end
24
36
 
25
37
  def perform_request(http, env)
26
38
  http.request env[:url], create_request(env)
27
39
  rescue Errno::ETIMEDOUT => error
28
- raise Faraday::Error::TimeoutError, error
40
+ raise Faraday::TimeoutError, error
29
41
  rescue Net::HTTP::Persistent::Error => error
30
42
  if error.message.include? 'Timeout'
31
- raise Faraday::Error::TimeoutError, error
43
+ raise Faraday::TimeoutError, error
32
44
  elsif error.message.include? 'connection refused'
33
- raise Faraday::Error::ConnectionFailed, error
45
+ raise Faraday::ConnectionFailed, error
34
46
  else
35
47
  raise
36
48
  end
37
49
  end
38
50
 
39
51
  def configure_ssl(http, ssl)
40
- http.verify_mode = ssl_verify_mode(ssl)
41
- http.cert_store = ssl_cert_store(ssl)
52
+ http_set(http, :verify_mode, ssl_verify_mode(ssl))
53
+ http_set(http, :cert_store, ssl_cert_store(ssl))
54
+
55
+ http_set(http, :certificate, ssl[:client_cert]) if ssl[:client_cert]
56
+ http_set(http, :private_key, ssl[:client_key]) if ssl[:client_key]
57
+ http_set(http, :ca_file, ssl[:ca_file]) if ssl[:ca_file]
58
+ http_set(http, :ssl_version, ssl[:version]) if ssl[:version]
59
+ end
42
60
 
43
- http.certificate = ssl[:client_cert] if ssl[:client_cert]
44
- http.private_key = ssl[:client_key] if ssl[:client_key]
45
- http.ca_file = ssl[:ca_file] if ssl[:ca_file]
46
- http.ssl_version = ssl[:version] if ssl[:version]
61
+ def http_set(http, attr, value)
62
+ if http.send(attr) != value
63
+ http.send("#{attr}=", value)
64
+ end
47
65
  end
48
66
  end
49
67
  end
@@ -5,11 +5,12 @@ module Faraday
5
5
 
6
6
  def call(env)
7
7
  super
8
-
9
8
  # TODO: support streaming requests
10
9
  env[:body] = env[:body].read if env[:body].respond_to? :read
11
10
 
12
- session = @session ||= create_session
11
+ session = ::Patron::Session.new
12
+ @config_block.call(session) if @config_block
13
+ configure_ssl(session, env[:ssl]) if env[:url].scheme == 'https' and env[:ssl]
13
14
 
14
15
  if req = env[:request]
15
16
  session.timeout = session.connect_timeout = req[:timeout] if req[:timeout]
@@ -27,7 +28,7 @@ module Faraday
27
28
  data = env[:body] ? env[:body].to_s : nil
28
29
  session.request(env[:method], env[:url].to_s, env[:request_headers], :data => data)
29
30
  rescue Errno::ECONNREFUSED, ::Patron::ConnectionFailed
30
- raise Error::ConnectionFailed, $!
31
+ raise Faraday::ConnectionFailed, $!
31
32
  end
32
33
 
33
34
  # Remove the "HTTP/1.1 200", leaving just the reason phrase
@@ -37,16 +38,16 @@ module Faraday
37
38
 
38
39
  @app.call env
39
40
  rescue ::Patron::TimeoutError => err
40
- if err.message == "Connection time-out"
41
- raise Faraday::Error::ConnectionFailed, err
41
+ if connection_timed_out_message?(err.message)
42
+ raise Faraday::ConnectionFailed, err
42
43
  else
43
- raise Faraday::Error::TimeoutError, err
44
+ raise Faraday::TimeoutError, err
44
45
  end
45
46
  rescue ::Patron::Error => err
46
47
  if err.message.include?("code 407")
47
- raise Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
48
+ raise Faraday::ConnectionFailed, %{407 "Proxy Authentication Required "}
48
49
  else
49
- raise Error::ConnectionFailed, err
50
+ raise Faraday::ConnectionFailed, err
50
51
  end
51
52
  end
52
53
 
@@ -65,12 +66,30 @@ module Faraday
65
66
  end
66
67
  end
67
68
 
68
- def create_session
69
- session = ::Patron::Session.new
70
- session.insecure = true
71
- @config_block.call(session) if @config_block
72
- session
69
+ def configure_ssl(session, ssl)
70
+ if ssl.fetch(:verify, true)
71
+ session.cacert = ssl[:ca_file]
72
+ else
73
+ session.insecure = true
74
+ end
75
+ end
76
+
77
+ private
78
+
79
+ CURL_TIMEOUT_MESSAGES = [ "Connection time-out",
80
+ "Connection timed out",
81
+ "Timed out before name resolve",
82
+ "server connect has timed out",
83
+ "Resolving timed out",
84
+ "name lookup timed out",
85
+ "timed out before SSL",
86
+ "connect() timed out"
87
+ ].freeze
88
+
89
+ def connection_timed_out_message?(message)
90
+ CURL_TIMEOUT_MESSAGES.any? { |curl_message| message.include?(curl_message) }
73
91
  end
92
+
74
93
  end
75
94
  end
76
95
  end
@@ -41,7 +41,7 @@ module Faraday
41
41
 
42
42
  timeout = env[:request][:timeout] || env[:request][:open_timeout]
43
43
  response = if timeout
44
- Timer.timeout(timeout, Faraday::Error::TimeoutError) { execute_request(env, rack_env) }
44
+ Timer.timeout(timeout, Faraday::TimeoutError) { execute_request(env, rack_env) }
45
45
  else
46
46
  execute_request(env, rack_env)
47
47
  end
@@ -53,17 +53,17 @@ module Faraday
53
53
  @stack.empty?
54
54
  end
55
55
 
56
- def match(request_method, path, headers, body)
56
+ def match(request_method, host, path, headers, body)
57
57
  return false if !@stack.key?(request_method)
58
58
  stack = @stack[request_method]
59
59
  consumed = (@consumed[request_method] ||= [])
60
60
 
61
- stub, meta = matches?(stack, path, headers, body)
61
+ stub, meta = matches?(stack, host, path, headers, body)
62
62
  if stub
63
63
  consumed << stack.delete(stub)
64
64
  return stub, meta
65
65
  end
66
- matches?(consumed, path, headers, body)
66
+ matches?(consumed, host, path, headers, body)
67
67
  end
68
68
 
69
69
  def get(path, headers = {}, &block)
@@ -110,29 +110,35 @@ module Faraday
110
110
  protected
111
111
 
112
112
  def new_stub(request_method, path, headers = {}, body=nil, &block)
113
- normalized_path = path.is_a?(Regexp) ? path : Faraday::Utils.normalize_path(path)
114
- (@stack[request_method] ||= []) << Stub.new(normalized_path, headers, body, block)
113
+ normalized_path, host =
114
+ if path.is_a?(Regexp)
115
+ path
116
+ else
117
+ [Faraday::Utils.normalize_path(path), Faraday::Utils.URI(path).host]
118
+ end
119
+
120
+ (@stack[request_method] ||= []) << Stub.new(host, normalized_path, headers, body, block)
115
121
  end
116
122
 
117
- def matches?(stack, path, headers, body)
123
+ def matches?(stack, host, path, headers, body)
118
124
  stack.each do |stub|
119
- match_result, meta = stub.matches?(path, headers, body)
125
+ match_result, meta = stub.matches?(host, path, headers, body)
120
126
  return stub, meta if match_result
121
127
  end
122
128
  nil
123
129
  end
124
130
  end
125
131
 
126
- class Stub < Struct.new(:path, :params, :headers, :body, :block)
127
- def initialize(full, headers, body, block)
132
+ class Stub < Struct.new(:host, :path, :params, :headers, :body, :block)
133
+ def initialize(host, full, headers, body, block)
128
134
  path, query = full.respond_to?(:split) ? full.split("?") : full
129
135
  params = query ?
130
136
  Faraday::Utils.parse_nested_query(query) :
131
137
  {}
132
- super(path, params, headers, body, block)
138
+ super(host, path, params, headers, body, block)
133
139
  end
134
140
 
135
- def matches?(request_uri, request_headers, request_body)
141
+ def matches?(request_host, request_uri, request_headers, request_body)
136
142
  request_path, request_query = request_uri.split('?')
137
143
  request_params = request_query ?
138
144
  Faraday::Utils.parse_nested_query(request_query) :
@@ -140,7 +146,8 @@ module Faraday
140
146
  # meta is a hash use as carrier
141
147
  # that will be yielded to consumer block
142
148
  meta = {}
143
- return path_match?(request_path, meta) &&
149
+ return (host.nil? || host == request_host) &&
150
+ path_match?(request_path, meta) &&
144
151
  params_match?(request_params) &&
145
152
  (body.to_s.size.zero? || request_body == body) &&
146
153
  headers_match?(request_headers), meta
@@ -183,10 +190,11 @@ module Faraday
183
190
 
184
191
  def call(env)
185
192
  super
193
+ host = env[:url].host
186
194
  normalized_path = Faraday::Utils.normalize_path(env[:url])
187
195
  params_encoder = env.request.params_encoder || Faraday::Utils.default_params_encoder
188
196
 
189
- stub, meta = stubs.match(env[:method], normalized_path, env.request_headers, env[:body])
197
+ stub, meta = stubs.match(env[:method], host, normalized_path, env.request_headers, env[:body])
190
198
  if stub
191
199
  env[:params] = (query = env[:url].query) ?
192
200
  params_encoder.decode(query) : {}
@@ -1,123 +1,12 @@
1
1
  module Faraday
2
2
  class Adapter
3
+ # This class is just a stub, the real adapter is in https://github.com/philsturgeon/typhoeus/blob/master/lib/typhoeus/adapters/faraday.rb
3
4
  class Typhoeus < Faraday::Adapter
4
- self.supports_parallel = true
5
-
6
- def self.setup_parallel_manager(options = {})
7
- options.empty? ? ::Typhoeus::Hydra.hydra : ::Typhoeus::Hydra.new(options)
8
- end
5
+ # Needs to define this method in order to support Typhoeus <= 1.3.0
6
+ def call; end
9
7
 
10
8
  dependency 'typhoeus'
11
-
12
- def call(env)
13
- super
14
- perform_request env
15
- @app.call env
16
- end
17
-
18
- def perform_request(env)
19
- read_body env
20
-
21
- hydra = env[:parallel_manager] || self.class.setup_parallel_manager
22
- hydra.queue request(env)
23
- hydra.run unless parallel?(env)
24
- rescue Errno::ECONNREFUSED
25
- raise Error::ConnectionFailed, $!
26
- end
27
-
28
- # TODO: support streaming requests
29
- def read_body(env)
30
- env[:body] = env[:body].read if env[:body].respond_to? :read
31
- end
32
-
33
- def request(env)
34
- method = env[:method]
35
- # For some reason, prevents Typhoeus from using "100-continue".
36
- # We want this because Webrick 1.3.1 can't seem to handle it w/ PUT.
37
- method = method.to_s.upcase if method == :put
38
-
39
- req = ::Typhoeus::Request.new env[:url].to_s,
40
- :method => method,
41
- :body => env[:body],
42
- :headers => env[:request_headers],
43
- :disable_ssl_peer_verification => (env[:ssl] && env[:ssl].disable?)
44
-
45
- configure_ssl req, env
46
- configure_proxy req, env
47
- configure_timeout req, env
48
- configure_socket req, env
49
-
50
- req.on_complete do |resp|
51
- if resp.timed_out?
52
- if parallel?(env)
53
- # TODO: error callback in async mode
54
- else
55
- raise Faraday::Error::TimeoutError, "request timed out"
56
- end
57
- end
58
-
59
- case resp.curl_return_code
60
- when 0
61
- # everything OK
62
- when 7
63
- raise Error::ConnectionFailed, resp.curl_error_message
64
- when 60
65
- raise Faraday::SSLError, resp.curl_error_message
66
- else
67
- raise Error::ClientError, resp.curl_error_message
68
- end
69
-
70
- save_response(env, resp.code, resp.body) do |response_headers|
71
- response_headers.parse resp.headers
72
- end
73
- # in async mode, :response is initialized at this point
74
- env[:response].finish(env) if parallel?(env)
75
- end
76
-
77
- req
78
- end
79
-
80
- def configure_ssl(req, env)
81
- ssl = env[:ssl]
82
-
83
- req.ssl_version = ssl[:version] if ssl[:version]
84
- req.ssl_cert = ssl[:client_cert] if ssl[:client_cert]
85
- req.ssl_key = ssl[:client_key] if ssl[:client_key]
86
- req.ssl_cacert = ssl[:ca_file] if ssl[:ca_file]
87
- req.ssl_capath = ssl[:ca_path] if ssl[:ca_path]
88
- end
89
-
90
- def configure_proxy(req, env)
91
- proxy = request_options(env)[:proxy]
92
- return unless proxy
93
-
94
- req.proxy = "#{proxy[:uri].host}:#{proxy[:uri].port}"
95
-
96
- if proxy[:user] && proxy[:password]
97
- req.proxy_username = proxy[:user]
98
- req.proxy_password = proxy[:password]
99
- end
100
- end
101
-
102
- def configure_timeout(req, env)
103
- env_req = request_options(env)
104
- req.timeout = req.connect_timeout = (env_req[:timeout] * 1000) if env_req[:timeout]
105
- req.connect_timeout = (env_req[:open_timeout] * 1000) if env_req[:open_timeout]
106
- end
107
-
108
- def configure_socket(req, env)
109
- if bind = request_options(env)[:bind]
110
- req.interface = bind[:host]
111
- end
112
- end
113
-
114
- def request_options(env)
115
- env[:request]
116
- end
117
-
118
- def parallel?(env)
119
- !!env[:parallel_manager]
120
- end
9
+ dependency 'typhoeus/adapters/faraday'
121
10
  end
122
11
  end
123
12
  end
@@ -40,6 +40,8 @@ module Faraday
40
40
  env.clear_body if env.needs_body?
41
41
  end
42
42
 
43
+ private
44
+
43
45
  def save_response(env, status, body, headers = nil, reason_phrase = nil)
44
46
  env.status = status
45
47
  env.body = body
@@ -53,9 +53,9 @@ module Faraday
53
53
  autoload_all 'faraday/adapter',
54
54
  :NetHttp => 'net_http',
55
55
  :NetHttpPersistent => 'net_http_persistent',
56
- :Typhoeus => 'typhoeus',
57
56
  :EMSynchrony => 'em_synchrony',
58
57
  :EMHttp => 'em_http',
58
+ :Typhoeus => 'typhoeus',
59
59
  :Patron => 'patron',
60
60
  :Excon => 'excon',
61
61
  :Test => 'test',
@@ -39,6 +39,9 @@ module Faraday
39
39
  # Public: Sets the default parallel manager for this connection.
40
40
  attr_writer :default_parallel_manager
41
41
 
42
+ # Public: Gets or Sets the Hash proxy options.
43
+ # attr_reader :proxy
44
+
42
45
  # Public: Initializes a new Faraday::Connection.
43
46
  #
44
47
  # url - URI or String base URL to use as a prefix for all
@@ -55,9 +58,9 @@ module Faraday
55
58
  # :user - String (optional)
56
59
  # :password - String (optional)
57
60
  def initialize(url = nil, options = nil)
58
- options = ConnectionOptions.from(options) unless options and options.is_a?(ConnectionOptions)
61
+ options = ConnectionOptions.from(options)
59
62
 
60
- if url.is_a?(Hash)
63
+ if url.is_a?(Hash) || url.is_a?(ConnectionOptions)
61
64
  options = options.merge(url)
62
65
  url = options.url
63
66
  end
@@ -79,14 +82,9 @@ module Faraday
79
82
  @params.update(options.params) if options.params
80
83
  @headers.update(options.headers) if options.headers
81
84
 
82
- @proxy = nil
83
- proxy(options.fetch(:proxy) {
84
- uri = ENV['http_proxy']
85
- if uri && !uri.empty?
86
- uri = 'http://' + uri if uri !~ /^http/i
87
- uri
88
- end
89
- })
85
+ @manual_proxy = !!options.proxy
86
+ @proxy = options.proxy ? ProxyOptions.from(options.proxy) : proxy_from_env(url)
87
+ @temp_proxy = @proxy
90
88
 
91
89
  yield(self) if block_given?
92
90
 
@@ -283,9 +281,17 @@ module Faraday
283
281
  # Public: Gets or Sets the Hash proxy options.
284
282
  def proxy(arg = nil)
285
283
  return @proxy if arg.nil?
284
+ warn 'Warning: use of proxy(new_value) to set connection proxy have been DEPRECATED and will be removed in Faraday 1.0'
285
+ @manual_proxy = true
286
286
  @proxy = ProxyOptions.from(arg)
287
287
  end
288
288
 
289
+ # Public: Sets the Hash proxy options.
290
+ def proxy=(new_value)
291
+ @manual_proxy = true
292
+ @proxy = new_value ? ProxyOptions.from(new_value) : nil
293
+ end
294
+
289
295
  def_delegators :url_prefix, :scheme, :scheme=, :host, :host=, :port, :port=
290
296
  def_delegator :url_prefix, :path, :path_prefix
291
297
 
@@ -304,7 +310,7 @@ module Faraday
304
310
  #
305
311
  # conn.get("nigiri?page=2") # accesses https://sushi.com/api/nigiri
306
312
  #
307
- # Returns the parsed URI from teh given input..
313
+ # Returns the parsed URI from the given input..
308
314
  def url_prefix=(url, encoder = nil)
309
315
  uri = @url_prefix = Utils.URI(url)
310
316
  self.path_prefix = uri.path
@@ -367,7 +373,11 @@ module Faraday
367
373
  raise ArgumentError, "unknown http method: #{method}"
368
374
  end
369
375
 
376
+ # Resets temp_proxy
377
+ @temp_proxy = proxy_for_request(url)
378
+
370
379
  request = build_request(method) do |req|
380
+ req.options = req.options.merge(:proxy => @temp_proxy)
371
381
  req.url(url) if url
372
382
  req.headers.update(headers) if headers
373
383
  req.body = body if body
@@ -384,7 +394,7 @@ module Faraday
384
394
  Request.create(method) do |req|
385
395
  req.params = self.params.dup
386
396
  req.headers = self.headers.dup
387
- req.options = self.options.merge(:proxy => self.proxy)
397
+ req.options = self.options
388
398
  yield(req) if block_given?
389
399
  end
390
400
  end
@@ -433,5 +443,42 @@ module Faraday
433
443
  header(*args)
434
444
  headers[Faraday::Request::Authorization::KEY] = header
435
445
  end
446
+
447
+ def proxy_from_env(url)
448
+ return if Faraday.ignore_env_proxy
449
+ uri = nil
450
+ if URI.parse('').respond_to?(:find_proxy)
451
+ case url
452
+ when String
453
+ uri = Utils.URI(url)
454
+ uri = URI.parse("#{uri.scheme}://#{uri.hostname}").find_proxy
455
+ when URI
456
+ uri = url.find_proxy
457
+ when nil
458
+ uri = find_default_proxy
459
+ end
460
+ else
461
+ warn 'no_proxy is unsupported' if ENV['no_proxy'] || ENV['NO_PROXY']
462
+ uri = find_default_proxy
463
+ end
464
+ ProxyOptions.from(uri) if uri
465
+ end
466
+
467
+ def find_default_proxy
468
+ uri = ENV['http_proxy']
469
+ if uri && !uri.empty?
470
+ uri = 'http://' + uri if uri !~ /^http/i
471
+ uri
472
+ end
473
+ end
474
+
475
+ def proxy_for_request(url)
476
+ return self.proxy if @manual_proxy
477
+ if url && Utils.URI(url).absolute?
478
+ proxy_from_env(url)
479
+ else
480
+ self.proxy
481
+ end
482
+ end
436
483
  end
437
484
  end