faraday 0.9.1 → 0.9.2
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.
- data/LICENSE.md +1 -1
- data/README.md +41 -16
- data/lib/faraday.rb +1 -1
- data/lib/faraday/adapter/em_synchrony.rb +8 -0
- data/lib/faraday/adapter/excon.rb +1 -0
- data/lib/faraday/adapter/httpclient.rb +14 -3
- data/lib/faraday/adapter/net_http.rb +2 -2
- data/lib/faraday/adapter/net_http_persistent.rb +2 -1
- data/lib/faraday/adapter/patron.rb +8 -2
- data/lib/faraday/connection.rb +8 -3
- data/lib/faraday/options.rb +9 -0
- data/lib/faraday/parameters.rb +54 -38
- data/lib/faraday/rack_builder.rb +3 -2
- data/lib/faraday/request/retry.rb +9 -3
- data/lib/faraday/response.rb +2 -2
- data/lib/faraday/utils.rb +13 -1
- metadata +61 -124
- checksums.yaml +0 -7
- data/.document +0 -6
- data/CHANGELOG.md +0 -20
- data/CONTRIBUTING.md +0 -36
- data/Gemfile +0 -25
- data/Rakefile +0 -71
- data/faraday.gemspec +0 -34
- data/script/cached-bundle +0 -46
- data/script/console +0 -7
- data/script/generate_certs +0 -42
- data/script/package +0 -7
- data/script/proxy-server +0 -42
- data/script/release +0 -17
- data/script/s3-put +0 -71
- data/script/server +0 -36
- data/script/test +0 -172
- data/test/adapters/default_test.rb +0 -14
- data/test/adapters/em_http_test.rb +0 -20
- data/test/adapters/em_synchrony_test.rb +0 -20
- data/test/adapters/excon_test.rb +0 -20
- data/test/adapters/httpclient_test.rb +0 -21
- data/test/adapters/integration.rb +0 -254
- data/test/adapters/logger_test.rb +0 -82
- data/test/adapters/net_http_persistent_test.rb +0 -20
- data/test/adapters/net_http_test.rb +0 -14
- data/test/adapters/patron_test.rb +0 -20
- data/test/adapters/rack_test.rb +0 -31
- data/test/adapters/test_middleware_test.rb +0 -114
- data/test/adapters/typhoeus_test.rb +0 -28
- data/test/authentication_middleware_test.rb +0 -65
- data/test/composite_read_io_test.rb +0 -111
- data/test/connection_test.rb +0 -522
- data/test/env_test.rb +0 -218
- data/test/helper.rb +0 -81
- data/test/live_server.rb +0 -67
- data/test/middleware/instrumentation_test.rb +0 -88
- data/test/middleware/retry_test.rb +0 -177
- data/test/middleware_stack_test.rb +0 -173
- data/test/multibyte.txt +0 -1
- data/test/options_test.rb +0 -252
- data/test/parameters_test.rb +0 -64
- data/test/request_middleware_test.rb +0 -142
- data/test/response_middleware_test.rb +0 -72
- data/test/strawberry.rb +0 -2
- data/test/utils_test.rb +0 -58
data/LICENSE.md
CHANGED
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][]
|
@@ -64,6 +65,32 @@ stack and default adapter (see [Faraday::RackBuilder#initialize](https://github.
|
|
64
65
|
response = Faraday.get 'http://sushi.com/nigiri/sake.json'
|
65
66
|
```
|
66
67
|
|
68
|
+
### Changing how parameters are serialized
|
69
|
+
|
70
|
+
Sometimes you need to send the same URL parameter multiple times with different
|
71
|
+
values. This requires manually setting the parameter encoder and can be done on
|
72
|
+
either per-connection or per-request basis.
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
# per-connection setting
|
76
|
+
conn = Faraday.new :params_encoder => Faraday::FlatParamsEncoder
|
77
|
+
|
78
|
+
conn.get do |req|
|
79
|
+
# per-request setting:
|
80
|
+
# req.options.params_encoder = my_encoder
|
81
|
+
req.params['roll'] = ['california', 'philadelphia']
|
82
|
+
end
|
83
|
+
# GET 'http://sushi.com?roll=california&roll=philadelphia'
|
84
|
+
```
|
85
|
+
|
86
|
+
The value of Faraday `params_encoder` can be any object that responds to:
|
87
|
+
|
88
|
+
* `encode(hash) #=> String`
|
89
|
+
* `decode(string) #=> Hash`
|
90
|
+
|
91
|
+
The encoder will affect both how query strings are processed and how POST bodies
|
92
|
+
get serialized. The default encoder is Faraday::NestedParamsEncoder.
|
93
|
+
|
67
94
|
## Advanced middleware usage
|
68
95
|
|
69
96
|
The order in which middleware is stacked is important. Like with Rack, the
|
@@ -183,13 +210,9 @@ stubs.verify_stubbed_calls
|
|
183
210
|
This library aims to support and is [tested against][travis] the following Ruby
|
184
211
|
implementations:
|
185
212
|
|
186
|
-
*
|
187
|
-
*
|
188
|
-
*
|
189
|
-
* MRI 2.0.0
|
190
|
-
* MRI 2.1.0
|
191
|
-
* [JRuby][]
|
192
|
-
* [Rubinius][]
|
213
|
+
* Ruby 1.8.7+
|
214
|
+
* [JRuby][] 1.7+
|
215
|
+
* [Rubinius][] 2+
|
193
216
|
|
194
217
|
If something doesn't work on one of these Ruby versions, it's a bug.
|
195
218
|
|
@@ -209,12 +232,14 @@ of a major release, support for that Ruby version may be dropped.
|
|
209
232
|
Copyright (c) 2009-2013 [Rick Olson](mailto:technoweenie@gmail.com), Zack Hobson.
|
210
233
|
See [LICENSE][] for details.
|
211
234
|
|
212
|
-
[
|
213
|
-
[
|
214
|
-
[
|
215
|
-
[
|
235
|
+
[net_http]: http://ruby-doc.org/stdlib/libdoc/net/http/rdoc/Net/HTTP.html
|
236
|
+
[persistent]: https://github.com/drbrain/net-http-persistent
|
237
|
+
[travis]: http://travis-ci.org/lostisland/faraday
|
238
|
+
[excon]: https://github.com/geemus/excon#readme
|
239
|
+
[typhoeus]: https://github.com/typhoeus/typhoeus#readme
|
240
|
+
[patron]: http://toland.github.com/patron/
|
216
241
|
[eventmachine]: https://github.com/igrigorik/em-http-request#readme
|
217
|
-
[httpclient]:
|
218
|
-
[jruby]:
|
219
|
-
[rubinius]:
|
220
|
-
[license]:
|
242
|
+
[httpclient]: https://github.com/nahi/httpclient
|
243
|
+
[jruby]: http://jruby.org/
|
244
|
+
[rubinius]: http://rubini.us/
|
245
|
+
[license]: LICENSE.md
|
data/lib/faraday.rb
CHANGED
@@ -70,6 +70,14 @@ module Faraday
|
|
70
70
|
else
|
71
71
|
raise Error::ConnectionFailed, err
|
72
72
|
end
|
73
|
+
rescue Errno::ETIMEDOUT => err
|
74
|
+
raise Error::TimeoutError, err
|
75
|
+
rescue RuntimeError => err
|
76
|
+
if err.message == "connection closed by server"
|
77
|
+
raise Error::ConnectionFailed, err
|
78
|
+
else
|
79
|
+
raise
|
80
|
+
end
|
73
81
|
rescue => err
|
74
82
|
if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err
|
75
83
|
raise Faraday::SSLError, 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
|
@@ -37,7 +40,7 @@ module Faraday
|
|
37
40
|
save_response env, resp.status, resp.body, resp.headers
|
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)
|
@@ -54,7 +54,7 @@ module Faraday
|
|
54
54
|
end
|
55
55
|
|
56
56
|
@app.call env
|
57
|
-
rescue Timeout::Error => err
|
57
|
+
rescue Timeout::Error, Errno::ETIMEDOUT => err
|
58
58
|
raise Faraday::Error::TimeoutError, err
|
59
59
|
end
|
60
60
|
|
@@ -92,7 +92,7 @@ module Faraday
|
|
92
92
|
Net::HTTP::Proxy(proxy[:uri].host, proxy[:uri].port, proxy[:user], proxy[:password])
|
93
93
|
else
|
94
94
|
Net::HTTP
|
95
|
-
end.new(env[:url].host, env[:url].port)
|
95
|
+
end.new(env[:url].host, env[:url].port || (env[:url].scheme == 'https' ? 443 : 80))
|
96
96
|
end
|
97
97
|
|
98
98
|
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
|
@@ -56,8 +56,14 @@ module Faraday
|
|
56
56
|
# HAX: helps but doesn't work completely
|
57
57
|
# https://github.com/toland/patron/issues/34
|
58
58
|
::Patron::Request::VALID_ACTIONS.tap do |actions|
|
59
|
-
|
60
|
-
|
59
|
+
if actions[0].is_a?(Symbol)
|
60
|
+
actions << :patch unless actions.include? :patch
|
61
|
+
actions << :options unless actions.include? :options
|
62
|
+
else
|
63
|
+
# Patron 0.4.20 and up
|
64
|
+
actions << "PATCH" unless actions.include? "PATCH"
|
65
|
+
actions << "OPTIONS" unless actions.include? "OPTIONS"
|
66
|
+
end
|
61
67
|
end
|
62
68
|
end
|
63
69
|
|
data/lib/faraday/connection.rb
CHANGED
@@ -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,
|
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/options.rb
CHANGED
@@ -269,6 +269,15 @@ module Faraday
|
|
269
269
|
|
270
270
|
def_delegators :request, :params_encoder
|
271
271
|
|
272
|
+
# Public
|
273
|
+
def self.from(value)
|
274
|
+
env = super(value)
|
275
|
+
if value.respond_to?(:custom_members)
|
276
|
+
env.custom_members.update(value.custom_members)
|
277
|
+
end
|
278
|
+
env
|
279
|
+
end
|
280
|
+
|
272
281
|
# Public
|
273
282
|
def [](key)
|
274
283
|
if in_member_set?(key)
|
data/lib/faraday/parameters.rb
CHANGED
@@ -46,6 +46,8 @@ module Faraday
|
|
46
46
|
buffer << "#{to_query.call(new_parent, val)}&"
|
47
47
|
end
|
48
48
|
return buffer.chop
|
49
|
+
elsif value.nil?
|
50
|
+
return parent
|
49
51
|
else
|
50
52
|
encoded_value = escape(value)
|
51
53
|
return "#{parent}=#{encoded_value}"
|
@@ -63,50 +65,64 @@ module Faraday
|
|
63
65
|
|
64
66
|
def self.decode(query)
|
65
67
|
return nil if query == nil
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
68
|
+
|
69
|
+
params = {}
|
70
|
+
query.split("&").each do |pair|
|
71
|
+
next if pair.empty?
|
72
|
+
key, value = pair.split("=", 2)
|
73
|
+
key = unescape(key)
|
74
|
+
value = unescape(value.gsub(/\+/, ' ')) if value
|
75
|
+
|
76
|
+
subkeys = key.scan(/[^\[\]]+(?:\]?\[\])?/)
|
77
|
+
context = params
|
78
|
+
subkeys.each_with_index do |subkey, i|
|
79
|
+
is_array = subkey =~ /[\[\]]+\Z/
|
80
|
+
subkey = $` if is_array
|
81
|
+
last_subkey = i == subkeys.length - 1
|
82
|
+
|
83
|
+
if !last_subkey || is_array
|
84
|
+
value_type = is_array ? Array : Hash
|
85
|
+
if context[subkey] && !context[subkey].is_a?(value_type)
|
86
|
+
raise TypeError, "expected %s (got %s) for param `%s'" % [
|
87
|
+
value_type.name,
|
88
|
+
context[subkey].class.name,
|
89
|
+
subkey
|
90
|
+
]
|
91
|
+
end
|
92
|
+
context = (context[subkey] ||= value_type.new)
|
71
93
|
end
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
94
|
+
|
95
|
+
if context.is_a?(Array) && !is_array
|
96
|
+
if !context.last.is_a?(Hash) || context.last.has_key?(subkey)
|
97
|
+
context << {}
|
98
|
+
end
|
99
|
+
context = context.last
|
100
|
+
end
|
101
|
+
|
102
|
+
if last_subkey
|
103
|
+
if is_array
|
104
|
+
context << value
|
105
|
+
else
|
106
|
+
context[subkey] = value
|
107
|
+
end
|
77
108
|
end
|
78
|
-
else
|
79
|
-
hash
|
80
109
|
end
|
81
110
|
end
|
82
111
|
|
83
|
-
|
84
|
-
|
85
|
-
pair.split('=', 2) if pair && !pair.empty?
|
86
|
-
end).compact.inject(empty_accumulator.dup) do |accu, (key, value)|
|
87
|
-
key = unescape(key)
|
88
|
-
if value.kind_of?(String)
|
89
|
-
value = unescape(value.gsub(/\+/, ' '))
|
90
|
-
end
|
112
|
+
dehash(params, 0)
|
113
|
+
end
|
91
114
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
else
|
104
|
-
current_hash[subkeys.last] = value
|
105
|
-
end
|
106
|
-
accu
|
107
|
-
end).inject(empty_accumulator.dup) do |accu, (key, value)|
|
108
|
-
accu[key] = value.kind_of?(Hash) ? dehash.call(value) : value
|
109
|
-
accu
|
115
|
+
# Internal: convert a nested hash with purely numeric keys into an array.
|
116
|
+
# FIXME: this is not compatible with Rack::Utils.parse_nested_query
|
117
|
+
def self.dehash(hash, depth)
|
118
|
+
hash.each do |key, value|
|
119
|
+
hash[key] = dehash(value, depth + 1) if value.kind_of?(Hash)
|
120
|
+
end
|
121
|
+
|
122
|
+
if depth > 0 && !hash.empty? && hash.keys.all? { |k| k =~ /^\d+$/ }
|
123
|
+
hash.keys.sort.inject([]) { |all, key| all << hash[key] }
|
124
|
+
else
|
125
|
+
hash
|
110
126
|
end
|
111
127
|
end
|
112
128
|
end
|
data/lib/faraday/rack_builder.rb
CHANGED
@@ -151,8 +151,9 @@ module Faraday
|
|
151
151
|
lock!
|
152
152
|
to_app(lambda { |env|
|
153
153
|
response = Response.new
|
154
|
-
response.finish(env) unless env.parallel?
|
155
154
|
env.response = response
|
155
|
+
response.finish(env) unless env.parallel?
|
156
|
+
response
|
156
157
|
})
|
157
158
|
end
|
158
159
|
end
|
@@ -188,7 +189,7 @@ module Faraday
|
|
188
189
|
# :ssl - Hash of options for configuring SSL requests.
|
189
190
|
def build_env(connection, request)
|
190
191
|
Env.new(request.method, request.body,
|
191
|
-
connection.build_exclusive_url(request.path, request.params),
|
192
|
+
connection.build_exclusive_url(request.path, request.params, request.options.params_encoder),
|
192
193
|
request.options, request.headers, connection.ssl,
|
193
194
|
connection.parallel_manager)
|
194
195
|
end
|
@@ -22,8 +22,8 @@ module Faraday
|
|
22
22
|
|
23
23
|
IDEMPOTENT_METHODS = [:delete, :get, :head, :options, :put]
|
24
24
|
|
25
|
-
class Options < Faraday::Options.new(:max, :interval, :
|
26
|
-
:exceptions, :methods, :retry_if)
|
25
|
+
class Options < Faraday::Options.new(:max, :interval, :max_interval, :interval_randomness,
|
26
|
+
:backoff_factor, :exceptions, :methods, :retry_if)
|
27
27
|
DEFAULT_CHECK = lambda { |env,exception| false }
|
28
28
|
|
29
29
|
def self.from(value)
|
@@ -42,8 +42,12 @@ module Faraday
|
|
42
42
|
(self[:interval] ||= 0).to_f
|
43
43
|
end
|
44
44
|
|
45
|
+
def max_interval
|
46
|
+
(self[:max_interval] ||= Float::MAX).to_f
|
47
|
+
end
|
48
|
+
|
45
49
|
def interval_randomness
|
46
|
-
(self[:interval_randomness] ||= 0).
|
50
|
+
(self[:interval_randomness] ||= 0).to_f
|
47
51
|
end
|
48
52
|
|
49
53
|
def backoff_factor
|
@@ -73,6 +77,7 @@ module Faraday
|
|
73
77
|
# interval_randomness - The maximum random interval amount expressed
|
74
78
|
# as a float between 0 and 1 to use in addition to the
|
75
79
|
# interval. (default: 0)
|
80
|
+
# max_interval - An upper limit for the interval (default: Float::MAX)
|
76
81
|
# backoff_factor - The amount to multiple each successive retry's
|
77
82
|
# interval amount by in order to provide backoff
|
78
83
|
# (default: 1)
|
@@ -98,6 +103,7 @@ module Faraday
|
|
98
103
|
def sleep_amount(retries)
|
99
104
|
retry_index = @options.max - retries
|
100
105
|
current_interval = @options.interval * (@options.backoff_factor ** retry_index)
|
106
|
+
current_interval = [current_interval, @options.max_interval].min
|
101
107
|
random_interval = rand * @options.interval_randomness.to_f * @options.interval
|
102
108
|
current_interval + random_interval
|
103
109
|
end
|
data/lib/faraday/response.rb
CHANGED
@@ -61,8 +61,8 @@ module Faraday
|
|
61
61
|
|
62
62
|
def finish(env)
|
63
63
|
raise "response already finished" if finished?
|
64
|
-
@
|
65
|
-
@
|
64
|
+
@env = env.is_a?(Env) ? env : Env.from(env)
|
65
|
+
@on_complete_callbacks.each { |callback| callback.call(@env) }
|
66
66
|
return self
|
67
67
|
end
|
68
68
|
|