faraday 0.9.1 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.md +1 -1
  3. data/README.md +45 -16
  4. data/lib/faraday/adapter/em_http.rb +3 -1
  5. data/lib/faraday/adapter/em_http_ssl_patch.rb +1 -1
  6. data/lib/faraday/adapter/em_synchrony.rb +11 -1
  7. data/lib/faraday/adapter/excon.rb +2 -1
  8. data/lib/faraday/adapter/httpclient.rb +15 -4
  9. data/lib/faraday/adapter/net_http.rb +4 -3
  10. data/lib/faraday/adapter/net_http_persistent.rb +2 -1
  11. data/lib/faraday/adapter/patron.rb +12 -3
  12. data/lib/faraday/adapter/test.rb +64 -21
  13. data/lib/faraday/adapter.rb +2 -1
  14. data/lib/faraday/connection.rb +12 -7
  15. data/lib/faraday/error.rb +11 -1
  16. data/lib/faraday/options.rb +11 -1
  17. data/lib/faraday/parameters.rb +54 -38
  18. data/lib/faraday/rack_builder.rb +3 -2
  19. data/lib/faraday/request/retry.rb +9 -3
  20. data/lib/faraday/request.rb +2 -0
  21. data/lib/faraday/response/logger.rb +10 -3
  22. data/lib/faraday/response.rb +6 -2
  23. data/lib/faraday/utils.rb +14 -2
  24. data/lib/faraday.rb +5 -32
  25. metadata +7 -93
  26. data/.document +0 -6
  27. data/CHANGELOG.md +0 -20
  28. data/CONTRIBUTING.md +0 -36
  29. data/Gemfile +0 -25
  30. data/Rakefile +0 -71
  31. data/faraday.gemspec +0 -34
  32. data/script/cached-bundle +0 -46
  33. data/script/console +0 -7
  34. data/script/generate_certs +0 -42
  35. data/script/package +0 -7
  36. data/script/proxy-server +0 -42
  37. data/script/release +0 -17
  38. data/script/s3-put +0 -71
  39. data/script/server +0 -36
  40. data/script/test +0 -172
  41. data/test/adapters/default_test.rb +0 -14
  42. data/test/adapters/em_http_test.rb +0 -20
  43. data/test/adapters/em_synchrony_test.rb +0 -20
  44. data/test/adapters/excon_test.rb +0 -20
  45. data/test/adapters/httpclient_test.rb +0 -21
  46. data/test/adapters/integration.rb +0 -254
  47. data/test/adapters/logger_test.rb +0 -82
  48. data/test/adapters/net_http_persistent_test.rb +0 -20
  49. data/test/adapters/net_http_test.rb +0 -14
  50. data/test/adapters/patron_test.rb +0 -20
  51. data/test/adapters/rack_test.rb +0 -31
  52. data/test/adapters/test_middleware_test.rb +0 -114
  53. data/test/adapters/typhoeus_test.rb +0 -28
  54. data/test/authentication_middleware_test.rb +0 -65
  55. data/test/composite_read_io_test.rb +0 -111
  56. data/test/connection_test.rb +0 -522
  57. data/test/env_test.rb +0 -218
  58. data/test/helper.rb +0 -81
  59. data/test/live_server.rb +0 -67
  60. data/test/middleware/instrumentation_test.rb +0 -88
  61. data/test/middleware/retry_test.rb +0 -177
  62. data/test/middleware_stack_test.rb +0 -173
  63. data/test/multibyte.txt +0 -1
  64. data/test/options_test.rb +0 -252
  65. data/test/parameters_test.rb +0 -64
  66. data/test/request_middleware_test.rb +0 -142
  67. data/test/response_middleware_test.rb +0 -72
  68. data/test/strawberry.rb +0 -2
  69. data/test/utils_test.rb +0 -58
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1c31dbb021fc6a43b4f0b102a9a3ccf52a72303a
4
- data.tar.gz: 54da868027777adb5a21145bd6433b0154af2297
3
+ metadata.gz: fc2292832e97072ea9b3292a56ee1c87e7f9ec19
4
+ data.tar.gz: 9aea82166ae97ea282ba1a4b5efc4740effeea14
5
5
  SHA512:
6
- metadata.gz: 22c1c286687ca596bd1d6b7d9a6a3749731f6d8962a5bbbe7e1e39cf22e364b92010ae44446cf1804ba10567a2e6409cc2be537375d9f47ace9bca909196dcd3
7
- data.tar.gz: 7e8116cdeea918b8e7de661ec6d49d839960e26f136903e53db62e8cc353f89b3ac053d5efe6401995129418ae4dfce8fda9c8a471093223dca08002615d10e1
6
+ metadata.gz: ba7bc351e2111733af22e1666f86d877050cd3256d3322e0418773aaf1a8c7447a02a780b812b0f2549b558c4c38a606189dad3c2915ed48019def848b8bc65c
7
+ data.tar.gz: d3cbb3fa12d1e37f162930bab8be286ca6b384e2ce622e8ebff9087386902b50aa318a423d054138d87064601034470a45d072c85bda910d29fbb84150a22a5f
data/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009-2013 Rick Olson, Zack Hobson
1
+ Copyright (c) 2009-2015 Rick Olson, Zack Hobson
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -6,7 +6,8 @@ processing the request/response cycle.
6
6
 
7
7
  Faraday supports these adapters:
8
8
 
9
- * Net::HTTP
9
+ * [Net::HTTP][net_http] _(default)_
10
+ * [Net::HTTP::Persistent][persistent]
10
11
  * [Excon][]
11
12
  * [Typhoeus][]
12
13
  * [Patron][]
@@ -16,6 +17,10 @@ Faraday supports these adapters:
16
17
  It also includes a Rack adapter for hitting loaded Rack applications through
17
18
  Rack::Test, and a Test adapter for stubbing requests by hand.
18
19
 
20
+ ## API documentation
21
+
22
+ Available at [rubydoc.info](http://www.rubydoc.info/gems/faraday).
23
+
19
24
  ## Usage
20
25
 
21
26
  ```ruby
@@ -64,6 +69,32 @@ stack and default adapter (see [Faraday::RackBuilder#initialize](https://github.
64
69
  response = Faraday.get 'http://sushi.com/nigiri/sake.json'
65
70
  ```
66
71
 
72
+ ### Changing how parameters are serialized
73
+
74
+ Sometimes you need to send the same URL parameter multiple times with different
75
+ values. This requires manually setting the parameter encoder and can be done on
76
+ either per-connection or per-request basis.
77
+
78
+ ```ruby
79
+ # per-connection setting
80
+ conn = Faraday.new :request => { :params_encoder => Faraday::FlatParamsEncoder }
81
+
82
+ conn.get do |req|
83
+ # per-request setting:
84
+ # req.options.params_encoder = my_encoder
85
+ req.params['roll'] = ['california', 'philadelphia']
86
+ end
87
+ # GET 'http://sushi.com?roll=california&roll=philadelphia'
88
+ ```
89
+
90
+ The value of Faraday `params_encoder` can be any object that responds to:
91
+
92
+ * `encode(hash) #=> String`
93
+ * `decode(string) #=> Hash`
94
+
95
+ The encoder will affect both how query strings are processed and how POST bodies
96
+ get serialized. The default encoder is Faraday::NestedParamsEncoder.
97
+
67
98
  ## Advanced middleware usage
68
99
 
69
100
  The order in which middleware is stacked is important. Like with Rack, the
@@ -183,13 +214,9 @@ stubs.verify_stubbed_calls
183
214
  This library aims to support and is [tested against][travis] the following Ruby
184
215
  implementations:
185
216
 
186
- * MRI 1.8.7
187
- * MRI 1.9.2
188
- * MRI 1.9.3
189
- * MRI 2.0.0
190
- * MRI 2.1.0
191
- * [JRuby][]
192
- * [Rubinius][]
217
+ * Ruby 1.9.3+
218
+ * [JRuby][] 1.7+
219
+ * [Rubinius][] 2+
193
220
 
194
221
  If something doesn't work on one of these Ruby versions, it's a bug.
195
222
 
@@ -209,12 +236,14 @@ of a major release, support for that Ruby version may be dropped.
209
236
  Copyright (c) 2009-2013 [Rick Olson](mailto:technoweenie@gmail.com), Zack Hobson.
210
237
  See [LICENSE][] for details.
211
238
 
212
- [travis]: http://travis-ci.org/lostisland/faraday
213
- [excon]: https://github.com/geemus/excon#readme
214
- [typhoeus]: https://github.com/typhoeus/typhoeus#readme
215
- [patron]: http://toland.github.com/patron/
239
+ [net_http]: http://ruby-doc.org/stdlib/libdoc/net/http/rdoc/Net/HTTP.html
240
+ [persistent]: https://github.com/drbrain/net-http-persistent
241
+ [travis]: https://travis-ci.org/lostisland/faraday
242
+ [excon]: https://github.com/excon/excon#readme
243
+ [typhoeus]: https://github.com/typhoeus/typhoeus#readme
244
+ [patron]: http://toland.github.io/patron/
216
245
  [eventmachine]: https://github.com/igrigorik/em-http-request#readme
217
- [httpclient]: https://github.com/nahi/httpclient
218
- [jruby]: http://jruby.org/
219
- [rubinius]: http://rubini.us/
220
- [license]: LICENSE.md
246
+ [httpclient]: https://github.com/nahi/httpclient
247
+ [jruby]: http://jruby.org/
248
+ [rubinius]: http://rubini.us/
249
+ [license]: LICENSE.md
@@ -140,7 +140,9 @@ module Faraday
140
140
  def perform_single_request(env)
141
141
  req = EventMachine::HttpRequest.new(env[:url], connection_config(env))
142
142
  req.setup_request(env[:method], request_config(env)).callback { |client|
143
- save_response(env, client.response_header.status, client.response) do |resp_headers|
143
+ status = client.response_header.status
144
+ reason = client.response_header.http_reason
145
+ save_response(env, status, client.response, nil, reason) do |resp_headers|
144
146
  client.response_header.each do |name, value|
145
147
  resp_headers[name.to_sym] = value
146
148
  end
@@ -39,7 +39,7 @@ module EmHttpSslPatch
39
39
  end
40
40
 
41
41
  def host
42
- parent.connopts.host
42
+ parent.uri.host
43
43
  end
44
44
 
45
45
  def certificate_store
@@ -54,7 +54,9 @@ module Faraday
54
54
 
55
55
  raise client.error if client.error
56
56
 
57
- save_response(env, client.response_header.status, client.response) do |resp_headers|
57
+ status = client.response_header.status
58
+ reason = client.response_header.http_reason
59
+ save_response(env, status, client.response, nil, reason) do |resp_headers|
58
60
  client.response_header.each do |name, value|
59
61
  resp_headers[name.to_sym] = value
60
62
  end
@@ -70,6 +72,14 @@ module Faraday
70
72
  else
71
73
  raise Error::ConnectionFailed, err
72
74
  end
75
+ rescue Errno::ETIMEDOUT => err
76
+ raise Error::TimeoutError, err
77
+ rescue RuntimeError => err
78
+ if err.message == "connection closed by server"
79
+ raise Error::ConnectionFailed, err
80
+ else
81
+ raise
82
+ end
73
83
  rescue => err
74
84
  if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err
75
85
  raise Faraday::SSLError, err
@@ -41,6 +41,7 @@ module Faraday
41
41
  if req[:proxy]
42
42
  opts[:proxy] = {
43
43
  :host => req[:proxy][:uri].host,
44
+ :hostname => req[:proxy][:uri].hostname,
44
45
  :port => req[:proxy][:uri].port,
45
46
  :scheme => req[:proxy][:uri].scheme,
46
47
  :user => req[:proxy][:user],
@@ -56,7 +57,7 @@ module Faraday
56
57
  :headers => env[:request_headers],
57
58
  :body => read_body(env)
58
59
 
59
- save_response(env, resp.status.to_i, resp.body, resp.headers)
60
+ save_response(env, resp.status.to_i, resp.body, resp.headers, resp.reason_phrase)
60
61
 
61
62
  @app.call env
62
63
  rescue ::Excon::Errors::SocketError => err
@@ -10,6 +10,9 @@ module Faraday
10
10
  def call(env)
11
11
  super
12
12
 
13
+ # enable compression
14
+ client.transparent_gzip_decompression = true
15
+
13
16
  if req = env[:request]
14
17
  if proxy = req[:proxy]
15
18
  configure_proxy proxy
@@ -34,10 +37,10 @@ module Faraday
34
37
  :body => env[:body],
35
38
  :header => env[:request_headers]
36
39
 
37
- save_response env, resp.status, resp.body, resp.headers
40
+ save_response env, resp.status, resp.body, resp.headers, resp.reason
38
41
 
39
42
  @app.call env
40
- rescue ::HTTPClient::TimeoutError
43
+ rescue ::HTTPClient::TimeoutError, Errno::ETIMEDOUT
41
44
  raise Faraday::Error::TimeoutError, $!
42
45
  rescue ::HTTPClient::BadResponseError => err
43
46
  if err.message.include?('status 407')
@@ -69,14 +72,14 @@ module Faraday
69
72
 
70
73
  def configure_ssl(ssl)
71
74
  ssl_config = client.ssl_config
75
+ ssl_config.verify_mode = ssl_verify_mode(ssl)
76
+ ssl_config.cert_store = ssl_cert_store(ssl)
72
77
 
73
78
  ssl_config.add_trust_ca ssl[:ca_file] if ssl[:ca_file]
74
79
  ssl_config.add_trust_ca ssl[:ca_path] if ssl[:ca_path]
75
- ssl_config.cert_store = ssl[:cert_store] if ssl[:cert_store]
76
80
  ssl_config.client_cert = ssl[:client_cert] if ssl[:client_cert]
77
81
  ssl_config.client_key = ssl[:client_key] if ssl[:client_key]
78
82
  ssl_config.verify_depth = ssl[:verify_depth] if ssl[:verify_depth]
79
- ssl_config.verify_mode = ssl_verify_mode(ssl)
80
83
  end
81
84
 
82
85
  def configure_timeouts(req)
@@ -92,6 +95,14 @@ module Faraday
92
95
  end
93
96
  end
94
97
 
98
+ def ssl_cert_store(ssl)
99
+ return ssl[:cert_store] if ssl[:cert_store]
100
+ # Use the default cert store by default, i.e. system ca certs
101
+ cert_store = OpenSSL::X509::Store.new
102
+ cert_store.set_default_paths
103
+ cert_store
104
+ end
105
+
95
106
  def ssl_verify_mode(ssl)
96
107
  ssl[:verify_mode] || begin
97
108
  if ssl.fetch(:verify, true)
@@ -17,6 +17,7 @@ module Faraday
17
17
  Errno::EHOSTUNREACH,
18
18
  Errno::EINVAL,
19
19
  Errno::ENETUNREACH,
20
+ Errno::EPIPE,
20
21
  Net::HTTPBadResponse,
21
22
  Net::HTTPHeaderSyntaxError,
22
23
  Net::ProtocolError,
@@ -46,7 +47,7 @@ module Faraday
46
47
  end
47
48
  end
48
49
 
49
- save_response(env, http_response.code.to_i, http_response.body || '') do |response_headers|
50
+ save_response(env, http_response.code.to_i, http_response.body || '', nil, http_response.message) do |response_headers|
50
51
  http_response.each_header do |key, value|
51
52
  response_headers[key] = value
52
53
  end
@@ -54,7 +55,7 @@ module Faraday
54
55
  end
55
56
 
56
57
  @app.call env
57
- rescue Timeout::Error => err
58
+ rescue Timeout::Error, Errno::ETIMEDOUT => err
58
59
  raise Faraday::Error::TimeoutError, err
59
60
  end
60
61
 
@@ -92,7 +93,7 @@ module Faraday
92
93
  Net::HTTP::Proxy(proxy[:uri].host, proxy[:uri].port, proxy[:user], proxy[:password])
93
94
  else
94
95
  Net::HTTP
95
- end.new(env[:url].host, env[:url].port)
96
+ end.new(env[:url].host, env[:url].port || (env[:url].scheme == 'https' ? 443 : 80))
96
97
  end
97
98
 
98
99
  def configure_ssl(http, ssl)
@@ -4,7 +4,6 @@
4
4
 
5
5
  module Faraday
6
6
  class Adapter
7
- # Experimental adapter for net-http-persistent
8
7
  class NetHttpPersistent < NetHttp
9
8
  dependency 'net/http/persistent'
10
9
 
@@ -24,6 +23,8 @@ module Faraday
24
23
 
25
24
  def perform_request(http, env)
26
25
  http.request env[:url], create_request(env)
26
+ rescue Errno::ETIMEDOUT => error
27
+ raise Faraday::Error::TimeoutError, error
27
28
  rescue Net::HTTP::Persistent::Error => error
28
29
  if error.message.include? 'Timeout'
29
30
  raise Faraday::Error::TimeoutError, error
@@ -35,7 +35,10 @@ module Faraday
35
35
  raise Error::ConnectionFailed, $!
36
36
  end
37
37
 
38
- save_response(env, response.status, response.body, response.headers)
38
+ # Remove the "HTTP/1.1 200", leaving just the reason phrase
39
+ reason_phrase = response.status_line.gsub(/^.* \d{3} /, '')
40
+
41
+ save_response(env, response.status, response.body, response.headers, reason_phrase)
39
42
 
40
43
  @app.call env
41
44
  rescue ::Patron::TimeoutError => err
@@ -56,8 +59,14 @@ module Faraday
56
59
  # HAX: helps but doesn't work completely
57
60
  # https://github.com/toland/patron/issues/34
58
61
  ::Patron::Request::VALID_ACTIONS.tap do |actions|
59
- actions << :patch unless actions.include? :patch
60
- actions << :options unless actions.include? :options
62
+ if actions[0].is_a?(Symbol)
63
+ actions << :patch unless actions.include? :patch
64
+ actions << :options unless actions.include? :options
65
+ else
66
+ # Patron 0.4.20 and up
67
+ actions << "PATCH" unless actions.include? "PATCH"
68
+ actions << "OPTIONS" unless actions.include? "OPTIONS"
69
+ end
61
70
  end
62
71
  end
63
72
 
@@ -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
 
@@ -33,12 +58,12 @@ module Faraday
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, 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, path, headers, body)
42
67
  end
43
68
 
44
69
  def get(path, headers = {}, &block)
@@ -85,18 +110,22 @@ 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)
113
+ normalized_path = path.is_a?(Regexp) ? path : Faraday::Utils.normalize_path(path)
89
114
  (@stack[request_method] ||= []) << Stub.new(normalized_path, headers, body, block)
90
115
  end
91
116
 
92
117
  def matches?(stack, path, headers, body)
93
- stack.detect { |stub| stub.matches?(path, headers, body) }
118
+ stack.each do |stub|
119
+ match_result, meta = stub.matches?(path, headers, body)
120
+ return stub, meta if match_result
121
+ end
122
+ nil
94
123
  end
95
124
  end
96
125
 
97
126
  class Stub < Struct.new(:path, :params, :headers, :body, :block)
98
127
  def initialize(full, headers, body, block)
99
- path, query = full.split('?')
128
+ path, query = full.respond_to?(:split) ? full.split("?") : full
100
129
  params = query ?
101
130
  Faraday::Utils.parse_nested_query(query) :
102
131
  {}
@@ -108,10 +137,21 @@ module Faraday
108
137
  request_params = request_query ?
109
138
  Faraday::Utils.parse_nested_query(request_query) :
110
139
  {}
111
- request_path == path &&
140
+ # meta is a hash use as carrier
141
+ # that will be yielded to consumer block
142
+ meta = {}
143
+ return path_match?(request_path, meta) &&
112
144
  params_match?(request_params) &&
113
145
  (body.to_s.size.zero? || request_body == body) &&
114
- headers_match?(request_headers)
146
+ headers_match?(request_headers), meta
147
+ end
148
+
149
+ def path_match?(request_path, meta)
150
+ if path.is_a? Regexp
151
+ !!(meta[:match_data] = path.match(request_path))
152
+ else
153
+ path == request_path
154
+ end
115
155
  end
116
156
 
117
157
  def params_match?(request_params)
@@ -146,11 +186,14 @@ module Faraday
146
186
  normalized_path = Faraday::Utils.normalize_path(env[:url])
147
187
  params_encoder = env.request.params_encoder || Faraday::Utils.default_params_encoder
148
188
 
149
- if stub = stubs.match(env[:method], normalized_path, env.request_headers, env[:body])
189
+ stub, meta = stubs.match(env[:method], normalized_path, env.request_headers, env[:body])
190
+ if stub
150
191
  env[:params] = (query = env[:url].query) ?
151
- params_encoder.decode(query) :
152
- {}
153
- status, headers, body = stub.block.call(env)
192
+ params_encoder.decode(query) : {}
193
+ block_arity = stub.block.arity
194
+ status, headers, body = (block_arity >= 0) ?
195
+ stub.block.call(*[env, meta].take(block_arity)) :
196
+ stub.block.call(env, meta)
154
197
  save_response(env, status, body, headers)
155
198
  else
156
199
  raise Stubs::NotFound, "no stubbed request for #{env[:method]} #{normalized_path} #{env[:body]}"
@@ -34,9 +34,10 @@ module Faraday
34
34
  env.clear_body if env.needs_body?
35
35
  end
36
36
 
37
- def save_response(env, status, body, headers = nil)
37
+ def save_response(env, status, body, headers = nil, reason_phrase = nil)
38
38
  env.status = status
39
39
  env.body = body
40
+ env.reason_phrase = reason_phrase && reason_phrase.to_s.strip
40
41
  env.response_headers = Utils::Headers.new.tap do |response_headers|
41
42
  response_headers.update headers unless headers.nil?
42
43
  yield(response_headers) if block_given?
@@ -56,7 +56,7 @@ module Faraday
56
56
  # :password - String (optional)
57
57
  def initialize(url = nil, options = nil)
58
58
  if url.is_a?(Hash)
59
- options = ConnectionOptions.from(url)
59
+ options = options ? options.merge(url) : ConnectionOptions.from(url)
60
60
  url = options.url
61
61
  else
62
62
  options = ConnectionOptions.from(options)
@@ -126,7 +126,7 @@ module Faraday
126
126
  # req.body = JSON.generate(:query => {...})
127
127
  # end
128
128
  #
129
- # Yields a Faraday::Response for further request customizations.
129
+ # Yields a Faraday::Request for further request customizations.
130
130
  # Returns a Faraday::Response.
131
131
  #
132
132
  # Signature
@@ -163,7 +163,7 @@ module Faraday
163
163
  # req.body = JSON.generate(:user => 'kimchy', ...)
164
164
  # end
165
165
  #
166
- # Yields a Faraday::Response for further request customizations.
166
+ # Yields a Faraday::Request for further request customizations.
167
167
  # Returns a Faraday::Response.
168
168
  #
169
169
  # Signature
@@ -358,7 +358,7 @@ module Faraday
358
358
  #
359
359
  # method - The Symbol HTTP method.
360
360
  # url - The String or URI to access.
361
- # body - The String body
361
+ # body - The request body that will eventually be converted to a string.
362
362
  # headers - Hash of unencoded HTTP header key/value pairs.
363
363
  #
364
364
  # Returns a Faraday::Response.
@@ -396,7 +396,7 @@ module Faraday
396
396
  # of the resulting url (default: nil).
397
397
  #
398
398
  # Returns the resulting URI instance.
399
- def build_exclusive_url(url = nil, params = nil)
399
+ def build_exclusive_url(url = nil, params = nil, params_encoder = nil)
400
400
  url = nil if url.respond_to?(:empty?) and url.empty?
401
401
  base = url_prefix
402
402
  if url and base.path and base.path !~ /\/$/
@@ -404,7 +404,7 @@ module Faraday
404
404
  base.path = base.path + '/' # ensure trailing slash
405
405
  end
406
406
  uri = url ? base + url : base
407
- uri.query = params.to_query(options.params_encoder) if params
407
+ uri.query = params.to_query(params_encoder || options.params_encoder) if params
408
408
  uri.query = nil if uri.query and uri.query.empty?
409
409
  uri
410
410
  end
@@ -413,7 +413,12 @@ module Faraday
413
413
  #
414
414
  # Returns a Faraday::Connection.
415
415
  def dup
416
- self.class.new(build_exclusive_url, :headers => headers.dup, :params => params.dup, :builder => builder.dup, :ssl => ssl.dup)
416
+ self.class.new(build_exclusive_url,
417
+ :headers => headers.dup,
418
+ :params => params.dup,
419
+ :builder => builder.dup,
420
+ :ssl => ssl.dup,
421
+ :request => options.dup)
417
422
  end
418
423
 
419
424
  # Internal: Yields username and password extracted from a URI if they both exist.
data/lib/faraday/error.rb CHANGED
@@ -29,7 +29,17 @@ module Faraday
29
29
  end
30
30
 
31
31
  def inspect
32
- %(#<#{self.class}>)
32
+ inner = ''
33
+ if @wrapped_exception
34
+ inner << " wrapped=#{@wrapped_exception.inspect}"
35
+ end
36
+ if @response
37
+ inner << " response=#{@response.inspect}"
38
+ end
39
+ if inner.empty?
40
+ inner << " #{super}"
41
+ end
42
+ %(#<#{self.class}#{inner}>)
33
43
  end
34
44
  end
35
45
 
@@ -252,7 +252,8 @@ module Faraday
252
252
  end
253
253
 
254
254
  class Env < Options.new(:method, :body, :url, :request, :request_headers,
255
- :ssl, :parallel_manager, :params, :response, :response_headers, :status)
255
+ :ssl, :parallel_manager, :params, :response, :response_headers, :status,
256
+ :reason_phrase)
256
257
 
257
258
  ContentLength = 'Content-Length'.freeze
258
259
  StatusesWithoutBody = Set.new [204, 304]
@@ -269,6 +270,15 @@ module Faraday
269
270
 
270
271
  def_delegators :request, :params_encoder
271
272
 
273
+ # Public
274
+ def self.from(value)
275
+ env = super(value)
276
+ if value.respond_to?(:custom_members)
277
+ env.custom_members.update(value.custom_members)
278
+ end
279
+ env
280
+ end
281
+
272
282
  # Public
273
283
  def [](key)
274
284
  if in_member_set?(key)