faraday 0.9.1 → 0.15.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 +189 -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 +7 -8
  8. data/lib/faraday/adapter/httpclient.rb +27 -5
  9. data/lib/faraday/adapter/net_http.rb +16 -9
  10. data/lib/faraday/adapter/net_http_persistent.rb +24 -9
  11. data/lib/faraday/adapter/patron.rb +40 -12
  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 +40 -18
  19. data/lib/faraday/parameters.rb +54 -38
  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 +80 -17
  24. data/lib/faraday/request.rb +2 -0
  25. data/lib/faraday/response/logger.rb +28 -7
  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 -93
  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
@@ -3,18 +3,13 @@ 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
11
  session = @session ||= create_session
12
+ configure_ssl(session, env[:ssl]) if env[:url].scheme == 'https' and env[:ssl]
18
13
 
19
14
  if req = env[:request]
20
15
  session.timeout = session.connect_timeout = req[:timeout] if req[:timeout]
@@ -35,11 +30,14 @@ module Faraday
35
30
  raise Error::ConnectionFailed, $!
36
31
  end
37
32
 
38
- save_response(env, response.status, response.body, response.headers)
33
+ # Remove the "HTTP/1.1 200", leaving just the reason phrase
34
+ reason_phrase = response.status_line.gsub(/^.* \d{3} /, '')
35
+
36
+ save_response(env, response.status, response.body, response.headers, reason_phrase)
39
37
 
40
38
  @app.call env
41
39
  rescue ::Patron::TimeoutError => err
42
- if err.message == "Connection time-out"
40
+ if connection_timed_out_message?(err.message)
43
41
  raise Faraday::Error::ConnectionFailed, err
44
42
  else
45
43
  raise Faraday::Error::TimeoutError, err
@@ -56,17 +54,47 @@ module Faraday
56
54
  # HAX: helps but doesn't work completely
57
55
  # https://github.com/toland/patron/issues/34
58
56
  ::Patron::Request::VALID_ACTIONS.tap do |actions|
59
- actions << :patch unless actions.include? :patch
60
- actions << :options unless actions.include? :options
57
+ if actions[0].is_a?(Symbol)
58
+ actions << :patch unless actions.include? :patch
59
+ actions << :options unless actions.include? :options
60
+ else
61
+ # Patron 0.4.20 and up
62
+ actions << "PATCH" unless actions.include? "PATCH"
63
+ actions << "OPTIONS" unless actions.include? "OPTIONS"
64
+ end
61
65
  end
62
66
  end
63
67
 
64
68
  def create_session
65
69
  session = ::Patron::Session.new
66
- session.insecure = true
67
- @block.call(session) if @block
70
+ @config_block.call(session) if @config_block
68
71
  session
69
72
  end
73
+
74
+ def configure_ssl(session, ssl)
75
+ if ssl.fetch(:verify, true)
76
+ session.cacert = ssl[:ca_file]
77
+ else
78
+ session.insecure = true
79
+ end
80
+ end
81
+
82
+ private
83
+
84
+ CURL_TIMEOUT_MESSAGES = [ "Connection time-out",
85
+ "Connection timed out",
86
+ "Timed out before name resolve",
87
+ "server connect has timed out",
88
+ "Resolving timed out",
89
+ "name lookup timed out",
90
+ "timed out before SSL",
91
+ "connect() timed out"
92
+ ].freeze
93
+
94
+ def connection_timed_out_message?(message)
95
+ CURL_TIMEOUT_MESSAGES.any? { |curl_message| message.include?(curl_message) }
96
+ end
97
+
70
98
  end
71
99
  end
72
100
  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
data/lib/faraday/error.rb CHANGED
@@ -1,9 +1,8 @@
1
1
  module Faraday
2
2
  class Error < StandardError; end
3
- class MissingDependency < Error; end
4
3
 
5
4
  class ClientError < Error
6
- attr_reader :response
5
+ attr_reader :response, :wrapped_exception
7
6
 
8
7
  def initialize(ex, response = nil)
9
8
  @wrapped_exception = nil
@@ -29,7 +28,17 @@ module Faraday
29
28
  end
30
29
 
31
30
  def inspect
32
- %(#<#{self.class}>)
31
+ inner = ''
32
+ if @wrapped_exception
33
+ inner << " wrapped=#{@wrapped_exception.inspect}"
34
+ end
35
+ if @response
36
+ inner << " response=#{@response.inspect}"
37
+ end
38
+ if inner.empty?
39
+ inner << " #{super}"
40
+ end
41
+ %(#<#{self.class}#{inner}>)
33
42
  end
34
43
  end
35
44
 
@@ -46,8 +55,12 @@ module Faraday
46
55
  class SSLError < ClientError
47
56
  end
48
57
 
49
- [:MissingDependency, :ClientError, :ConnectionFailed, :ResourceNotFound,
50
- :ParsingError, :TimeoutError, :SSLError].each do |const|
58
+ class RetriableResponse < ClientError; end
59
+
60
+ [:ClientError, :ConnectionFailed, :ResourceNotFound,
61
+ :ParsingError, :TimeoutError, :SSLError, :RetriableResponse].each do |const|
51
62
  Error.const_set(const, Faraday.const_get(const))
52
63
  end
64
+
65
+
53
66
  end