faraday 0.9.1 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE.md +1 -1
  3. data/README.md +192 -28
  4. data/lib/faraday/adapter/em_http.rb +8 -2
  5. data/lib/faraday/adapter/em_http_ssl_patch.rb +1 -1
  6. data/lib/faraday/adapter/em_synchrony.rb +16 -2
  7. data/lib/faraday/adapter/excon.rb +10 -8
  8. data/lib/faraday/adapter/httpclient.rb +27 -5
  9. data/lib/faraday/adapter/net_http.rb +34 -12
  10. data/lib/faraday/adapter/net_http_persistent.rb +35 -15
  11. data/lib/faraday/adapter/patron.rb +39 -16
  12. data/lib/faraday/adapter/test.rb +79 -28
  13. data/lib/faraday/adapter/typhoeus.rb +4 -115
  14. data/lib/faraday/adapter.rb +10 -1
  15. data/lib/faraday/autoload.rb +1 -1
  16. data/lib/faraday/connection.rb +72 -20
  17. data/lib/faraday/error.rb +18 -5
  18. data/lib/faraday/options.rb +42 -19
  19. data/lib/faraday/parameters.rb +56 -39
  20. data/lib/faraday/rack_builder.rb +27 -2
  21. data/lib/faraday/request/authorization.rb +1 -2
  22. data/lib/faraday/request/multipart.rb +7 -2
  23. data/lib/faraday/request/retry.rb +82 -18
  24. data/lib/faraday/request.rb +22 -0
  25. data/lib/faraday/response/logger.rb +29 -8
  26. data/lib/faraday/response.rb +6 -2
  27. data/lib/faraday/utils.rb +32 -3
  28. data/lib/faraday.rb +14 -34
  29. metadata +7 -94
  30. data/.document +0 -6
  31. data/CHANGELOG.md +0 -20
  32. data/CONTRIBUTING.md +0 -36
  33. data/Gemfile +0 -25
  34. data/Rakefile +0 -71
  35. data/faraday.gemspec +0 -34
  36. data/script/cached-bundle +0 -46
  37. data/script/console +0 -7
  38. data/script/generate_certs +0 -42
  39. data/script/package +0 -7
  40. data/script/proxy-server +0 -42
  41. data/script/release +0 -17
  42. data/script/s3-put +0 -71
  43. data/script/server +0 -36
  44. data/script/test +0 -172
  45. data/test/adapters/default_test.rb +0 -14
  46. data/test/adapters/em_http_test.rb +0 -20
  47. data/test/adapters/em_synchrony_test.rb +0 -20
  48. data/test/adapters/excon_test.rb +0 -20
  49. data/test/adapters/httpclient_test.rb +0 -21
  50. data/test/adapters/integration.rb +0 -254
  51. data/test/adapters/logger_test.rb +0 -82
  52. data/test/adapters/net_http_persistent_test.rb +0 -20
  53. data/test/adapters/net_http_test.rb +0 -14
  54. data/test/adapters/patron_test.rb +0 -20
  55. data/test/adapters/rack_test.rb +0 -31
  56. data/test/adapters/test_middleware_test.rb +0 -114
  57. data/test/adapters/typhoeus_test.rb +0 -28
  58. data/test/authentication_middleware_test.rb +0 -65
  59. data/test/composite_read_io_test.rb +0 -111
  60. data/test/connection_test.rb +0 -522
  61. data/test/env_test.rb +0 -218
  62. data/test/helper.rb +0 -81
  63. data/test/live_server.rb +0 -67
  64. data/test/middleware/instrumentation_test.rb +0 -88
  65. data/test/middleware/retry_test.rb +0 -177
  66. data/test/middleware_stack_test.rb +0 -173
  67. data/test/multibyte.txt +0 -1
  68. data/test/options_test.rb +0 -252
  69. data/test/parameters_test.rb +0 -64
  70. data/test/request_middleware_test.rb +0 -142
  71. data/test/response_middleware_test.rb +0 -72
  72. data/test/strawberry.rb +0 -2
  73. data/test/utils_test.rb +0 -58
@@ -1,15 +1,28 @@
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
- # Experimental adapter for net-http-persistent
8
3
  class NetHttpPersistent < NetHttp
9
4
  dependency 'net/http/persistent'
10
5
 
11
- def with_net_http_connection(env)
12
- if proxy = env[:request][:proxy]
6
+ private
7
+
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
25
+ if (proxy = env[:request][:proxy])
13
26
  proxy_uri = ::URI::HTTP === proxy[:uri] ? proxy[:uri].dup : ::URI.parse(proxy[:uri].to_s)
14
27
  proxy_uri.user = proxy_uri.password = nil
15
28
  # awful patch for net-http-persistent 2.8 not unescaping user/password
@@ -18,12 +31,13 @@ module Faraday
18
31
  define_method(:password) { proxy[:password] }
19
32
  end if proxy[:user]
20
33
  end
21
-
22
- yield Net::HTTP::Persistent.new 'Faraday', proxy_uri
34
+ proxy_uri
23
35
  end
24
36
 
25
37
  def perform_request(http, env)
26
38
  http.request env[:url], create_request(env)
39
+ rescue Errno::ETIMEDOUT => error
40
+ raise Faraday::Error::TimeoutError, error
27
41
  rescue Net::HTTP::Persistent::Error => error
28
42
  if error.message.include? 'Timeout'
29
43
  raise Faraday::Error::TimeoutError, error
@@ -35,13 +49,19 @@ module Faraday
35
49
  end
36
50
 
37
51
  def configure_ssl(http, ssl)
38
- http.verify_mode = ssl_verify_mode(ssl)
39
- 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
40
60
 
41
- http.certificate = ssl[:client_cert] if ssl[:client_cert]
42
- http.private_key = ssl[:client_key] if ssl[:client_key]
43
- http.ca_file = ssl[:ca_file] if ssl[:ca_file]
44
- 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
45
65
  end
46
66
  end
47
67
  end
@@ -3,18 +3,14 @@ module Faraday
3
3
  class Patron < Faraday::Adapter
4
4
  dependency 'patron'
5
5
 
6
- def initialize(app, &block)
7
- super(app)
8
- @block = block
9
- end
10
-
11
6
  def call(env)
12
7
  super
13
-
14
8
  # TODO: support streaming requests
15
9
  env[:body] = env[:body].read if env[:body].respond_to? :read
16
10
 
17
- 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]
18
14
 
19
15
  if req = env[:request]
20
16
  session.timeout = session.connect_timeout = req[:timeout] if req[:timeout]
@@ -35,11 +31,14 @@ module Faraday
35
31
  raise Error::ConnectionFailed, $!
36
32
  end
37
33
 
38
- save_response(env, response.status, response.body, response.headers)
34
+ # Remove the "HTTP/1.1 200", leaving just the reason phrase
35
+ reason_phrase = response.status_line.gsub(/^.* \d{3} /, '')
36
+
37
+ save_response(env, response.status, response.body, response.headers, reason_phrase)
39
38
 
40
39
  @app.call env
41
40
  rescue ::Patron::TimeoutError => err
42
- if err.message == "Connection time-out"
41
+ if connection_timed_out_message?(err.message)
43
42
  raise Faraday::Error::ConnectionFailed, err
44
43
  else
45
44
  raise Faraday::Error::TimeoutError, err
@@ -56,17 +55,41 @@ module Faraday
56
55
  # HAX: helps but doesn't work completely
57
56
  # https://github.com/toland/patron/issues/34
58
57
  ::Patron::Request::VALID_ACTIONS.tap do |actions|
59
- actions << :patch unless actions.include? :patch
60
- actions << :options unless actions.include? :options
58
+ if actions[0].is_a?(Symbol)
59
+ actions << :patch unless actions.include? :patch
60
+ actions << :options unless actions.include? :options
61
+ else
62
+ # Patron 0.4.20 and up
63
+ actions << "PATCH" unless actions.include? "PATCH"
64
+ actions << "OPTIONS" unless actions.include? "OPTIONS"
65
+ end
61
66
  end
62
67
  end
63
68
 
64
- def create_session
65
- session = ::Patron::Session.new
66
- session.insecure = true
67
- @block.call(session) if @block
68
- 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
69
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) }
91
+ end
92
+
70
93
  end
71
94
  end
72
95
  end
@@ -1,16 +1,41 @@
1
1
  module Faraday
2
2
  class Adapter
3
- # test = Faraday::Connection.new do
4
- # use Faraday::Adapter::Test do |stub|
5
- # stub.get '/nigiri/sake.json' do
6
- # [200, {}, 'hi world']
3
+ # Examples
4
+ #
5
+ # test = Faraday::Connection.new do
6
+ # use Faraday::Adapter::Test do |stub|
7
+ # # simply define matcher to match the request
8
+ # stub.get '/resource.json' do
9
+ # # return static content
10
+ # [200, {'Content-Type' => 'application/json'}, 'hi world']
11
+ # end
12
+ #
13
+ # # response with content generated based on request
14
+ # stub.get '/showget' do |env|
15
+ # [200, {'Content-Type' => 'text/plain'}, env[:method].to_s]
16
+ # end
17
+ #
18
+ # # regular expression can be used as matching filter
19
+ # stub.get /\A\/items\/(\d+)\z/ do |env, meta|
20
+ # # in case regular expression is used an instance of MatchData can be received
21
+ # [200, {'Content-Type' => 'text/plain'}, "showing item: #{meta[:match_data][1]}"]
22
+ # end
7
23
  # end
8
24
  # end
9
- # end
10
- #
11
- # resp = test.get '/nigiri/sake.json'
12
- # resp.body # => 'hi world'
25
+ #
26
+ # resp = test.get '/resource.json'
27
+ # resp.body # => 'hi world'
28
+ #
29
+ # resp = test.get '/showget'
30
+ # resp.body # => 'get'
31
+ #
32
+ # resp = test.get '/items/1'
33
+ # resp.body # => 'showing item: 1'
34
+ #
35
+ # resp = test.get '/items/2'
36
+ # resp.body # => 'showing item: 2'
13
37
  #
38
+
14
39
  class Test < Faraday::Adapter
15
40
  attr_accessor :stubs
16
41
 
@@ -28,17 +53,17 @@ module Faraday
28
53
  @stack.empty?
29
54
  end
30
55
 
31
- def match(request_method, path, headers, body)
56
+ def match(request_method, host, path, headers, body)
32
57
  return false if !@stack.key?(request_method)
33
58
  stack = @stack[request_method]
34
59
  consumed = (@consumed[request_method] ||= [])
35
60
 
36
- if stub = matches?(stack, path, headers, body)
61
+ stub, meta = matches?(stack, host, path, headers, body)
62
+ if stub
37
63
  consumed << stack.delete(stub)
38
- stub
39
- else
40
- matches?(consumed, path, headers, body)
64
+ return stub, meta
41
65
  end
66
+ matches?(consumed, host, path, headers, body)
42
67
  end
43
68
 
44
69
  def get(path, headers = {}, &block)
@@ -85,33 +110,55 @@ module Faraday
85
110
  protected
86
111
 
87
112
  def new_stub(request_method, path, headers = {}, body=nil, &block)
88
- normalized_path = Faraday::Utils.normalize_path(path)
89
- (@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)
90
121
  end
91
122
 
92
- def matches?(stack, path, headers, body)
93
- stack.detect { |stub| stub.matches?(path, headers, body) }
123
+ def matches?(stack, host, path, headers, body)
124
+ stack.each do |stub|
125
+ match_result, meta = stub.matches?(host, path, headers, body)
126
+ return stub, meta if match_result
127
+ end
128
+ nil
94
129
  end
95
130
  end
96
131
 
97
- class Stub < Struct.new(:path, :params, :headers, :body, :block)
98
- def initialize(full, headers, body, block)
99
- path, query = full.split('?')
132
+ class Stub < Struct.new(:host, :path, :params, :headers, :body, :block)
133
+ def initialize(host, full, headers, body, block)
134
+ path, query = full.respond_to?(:split) ? full.split("?") : full
100
135
  params = query ?
101
136
  Faraday::Utils.parse_nested_query(query) :
102
137
  {}
103
- super(path, params, headers, body, block)
138
+ super(host, path, params, headers, body, block)
104
139
  end
105
140
 
106
- def matches?(request_uri, request_headers, request_body)
141
+ def matches?(request_host, request_uri, request_headers, request_body)
107
142
  request_path, request_query = request_uri.split('?')
108
143
  request_params = request_query ?
109
144
  Faraday::Utils.parse_nested_query(request_query) :
110
145
  {}
111
- request_path == path &&
146
+ # meta is a hash use as carrier
147
+ # that will be yielded to consumer block
148
+ meta = {}
149
+ return (host.nil? || host == request_host) &&
150
+ path_match?(request_path, meta) &&
112
151
  params_match?(request_params) &&
113
152
  (body.to_s.size.zero? || request_body == body) &&
114
- headers_match?(request_headers)
153
+ headers_match?(request_headers), meta
154
+ end
155
+
156
+ def path_match?(request_path, meta)
157
+ if path.is_a? Regexp
158
+ !!(meta[:match_data] = path.match(request_path))
159
+ else
160
+ path == request_path
161
+ end
115
162
  end
116
163
 
117
164
  def params_match?(request_params)
@@ -143,14 +190,18 @@ module Faraday
143
190
 
144
191
  def call(env)
145
192
  super
193
+ host = env[:url].host
146
194
  normalized_path = Faraday::Utils.normalize_path(env[:url])
147
195
  params_encoder = env.request.params_encoder || Faraday::Utils.default_params_encoder
148
196
 
149
- if stub = 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])
198
+ if stub
150
199
  env[:params] = (query = env[:url].query) ?
151
- params_encoder.decode(query) :
152
- {}
153
- status, headers, body = stub.block.call(env)
200
+ params_encoder.decode(query) : {}
201
+ block_arity = stub.block.arity
202
+ status, headers, body = (block_arity >= 0) ?
203
+ stub.block.call(*[env, meta].take(block_arity)) :
204
+ stub.block.call(env, meta)
154
205
  save_response(env, status, body, headers)
155
206
  else
156
207
  raise Stubs::NotFound, "no stubbed request for #{env[:method]} #{normalized_path} #{env[:body]}"
@@ -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
@@ -30,13 +30,22 @@ module Faraday
30
30
  extend Parallelism
31
31
  self.supports_parallel = false
32
32
 
33
+ def initialize(app = nil, opts = {}, &block)
34
+ super(app)
35
+ @connection_options = opts
36
+ @config_block = block
37
+ end
38
+
33
39
  def call(env)
34
40
  env.clear_body if env.needs_body?
35
41
  end
36
42
 
37
- def save_response(env, status, body, headers = nil)
43
+ private
44
+
45
+ def save_response(env, status, body, headers = nil, reason_phrase = nil)
38
46
  env.status = status
39
47
  env.body = body
48
+ env.reason_phrase = reason_phrase && reason_phrase.to_s.strip
40
49
  env.response_headers = Utils::Headers.new.tap do |response_headers|
41
50
  response_headers.update headers unless headers.nil?
42
51
  yield(response_headers) if block_given?
@@ -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,11 +58,11 @@ module Faraday
55
58
  # :user - String (optional)
56
59
  # :password - String (optional)
57
60
  def initialize(url = nil, options = nil)
58
- if url.is_a?(Hash)
59
- options = ConnectionOptions.from(url)
61
+ options = ConnectionOptions.from(options)
62
+
63
+ if url.is_a?(Hash) || url.is_a?(ConnectionOptions)
64
+ options = options.merge(url)
60
65
  url = options.url
61
- else
62
- options = ConnectionOptions.from(options)
63
66
  end
64
67
 
65
68
  @parallel_manager = nil
@@ -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
 
@@ -126,7 +124,7 @@ module Faraday
126
124
  # req.body = JSON.generate(:query => {...})
127
125
  # end
128
126
  #
129
- # Yields a Faraday::Response for further request customizations.
127
+ # Yields a Faraday::Request for further request customizations.
130
128
  # Returns a Faraday::Response.
131
129
  #
132
130
  # Signature
@@ -163,7 +161,7 @@ module Faraday
163
161
  # req.body = JSON.generate(:user => 'kimchy', ...)
164
162
  # end
165
163
  #
166
- # Yields a Faraday::Response for further request customizations.
164
+ # Yields a Faraday::Request for further request customizations.
167
165
  # Returns a Faraday::Response.
168
166
  #
169
167
  # Signature
@@ -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
@@ -358,7 +364,7 @@ module Faraday
358
364
  #
359
365
  # method - The Symbol HTTP method.
360
366
  # url - The String or URI to access.
361
- # body - The String body
367
+ # body - The request body that will eventually be converted to a string.
362
368
  # headers - Hash of unencoded HTTP header key/value pairs.
363
369
  #
364
370
  # Returns a Faraday::Response.
@@ -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
@@ -396,7 +406,7 @@ module Faraday
396
406
  # of the resulting url (default: nil).
397
407
  #
398
408
  # Returns the resulting URI instance.
399
- def build_exclusive_url(url = nil, params = nil)
409
+ def build_exclusive_url(url = nil, params = nil, params_encoder = nil)
400
410
  url = nil if url.respond_to?(:empty?) and url.empty?
401
411
  base = url_prefix
402
412
  if url and base.path and base.path !~ /\/$/
@@ -404,7 +414,7 @@ module Faraday
404
414
  base.path = base.path + '/' # ensure trailing slash
405
415
  end
406
416
  uri = url ? base + url : base
407
- uri.query = params.to_query(options.params_encoder) if params
417
+ uri.query = params.to_query(params_encoder || options.params_encoder) if params
408
418
  uri.query = nil if uri.query and uri.query.empty?
409
419
  uri
410
420
  end
@@ -413,7 +423,12 @@ module Faraday
413
423
  #
414
424
  # Returns a Faraday::Connection.
415
425
  def dup
416
- self.class.new(build_exclusive_url, :headers => headers.dup, :params => params.dup, :builder => builder.dup, :ssl => ssl.dup)
426
+ self.class.new(build_exclusive_url,
427
+ :headers => headers.dup,
428
+ :params => params.dup,
429
+ :builder => builder.dup,
430
+ :ssl => ssl.dup,
431
+ :request => options.dup)
417
432
  end
418
433
 
419
434
  # Internal: Yields username and password extracted from a URI if they both exist.
@@ -428,5 +443,42 @@ module Faraday
428
443
  header(*args)
429
444
  headers[Faraday::Request::Authorization::KEY] = header
430
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
431
483
  end
432
484
  end