faraday 0.16.2 → 0.17.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.
- checksums.yaml +4 -4
- data/LICENSE.md +1 -1
- data/README.md +347 -18
- data/lib/faraday.rb +175 -93
- data/lib/faraday/adapter.rb +22 -36
- data/lib/faraday/adapter/em_http.rb +99 -142
- data/lib/faraday/adapter/em_http_ssl_patch.rb +17 -23
- data/lib/faraday/adapter/em_synchrony.rb +60 -104
- data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +15 -18
- data/lib/faraday/adapter/excon.rb +55 -100
- data/lib/faraday/adapter/httpclient.rb +39 -61
- data/lib/faraday/adapter/net_http.rb +51 -104
- data/lib/faraday/adapter/net_http_persistent.rb +27 -48
- data/lib/faraday/adapter/patron.rb +35 -54
- data/lib/faraday/adapter/rack.rb +12 -28
- data/lib/faraday/adapter/test.rb +53 -86
- data/lib/faraday/adapter/typhoeus.rb +1 -4
- data/lib/faraday/autoload.rb +36 -47
- data/lib/faraday/connection.rb +179 -321
- data/lib/faraday/error.rb +32 -80
- data/lib/faraday/middleware.rb +28 -4
- data/lib/faraday/options.rb +186 -35
- data/lib/faraday/parameters.rb +197 -4
- data/lib/faraday/rack_builder.rb +56 -67
- data/lib/faraday/request.rb +36 -68
- data/lib/faraday/request/authorization.rb +30 -42
- data/lib/faraday/request/basic_authentication.rb +7 -14
- data/lib/faraday/request/instrumentation.rb +27 -45
- data/lib/faraday/request/multipart.rb +48 -79
- data/lib/faraday/request/retry.rb +170 -197
- data/lib/faraday/request/token_authentication.rb +10 -15
- data/lib/faraday/request/url_encoded.rb +23 -41
- data/lib/faraday/response.rb +16 -23
- data/lib/faraday/response/logger.rb +69 -22
- data/lib/faraday/response/raise_error.rb +14 -36
- data/lib/faraday/upload_io.rb +67 -0
- data/lib/faraday/utils.rb +245 -28
- metadata +5 -22
- data/lib/faraday/adapter_registry.rb +0 -28
- data/lib/faraday/dependency_loader.rb +0 -37
- data/lib/faraday/deprecated_class.rb +0 -28
- data/lib/faraday/encoders/flat_params_encoder.rb +0 -94
- data/lib/faraday/encoders/nested_params_encoder.rb +0 -171
- data/lib/faraday/file_part.rb +0 -128
- data/lib/faraday/logging/formatter.rb +0 -92
- data/lib/faraday/middleware_registry.rb +0 -129
- data/lib/faraday/options/connection_options.rb +0 -22
- data/lib/faraday/options/env.rb +0 -181
- data/lib/faraday/options/proxy_options.rb +0 -28
- data/lib/faraday/options/request_options.rb +0 -21
- data/lib/faraday/options/ssl_options.rb +0 -59
- data/lib/faraday/param_part.rb +0 -53
- data/lib/faraday/utils/headers.rb +0 -139
- data/lib/faraday/utils/params_hash.rb +0 -61
- data/spec/external_adapters/faraday_specs_setup.rb +0 -14
data/lib/faraday/parameters.rb
CHANGED
@@ -1,5 +1,198 @@
|
|
1
|
-
|
1
|
+
require "forwardable"
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
module Faraday
|
4
|
+
module NestedParamsEncoder
|
5
|
+
class << self
|
6
|
+
extend Forwardable
|
7
|
+
def_delegators :'Faraday::Utils', :escape, :unescape
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.encode(params)
|
11
|
+
return nil if params == nil
|
12
|
+
|
13
|
+
if !params.is_a?(Array)
|
14
|
+
if !params.respond_to?(:to_hash)
|
15
|
+
raise TypeError,
|
16
|
+
"Can't convert #{params.class} into Hash."
|
17
|
+
end
|
18
|
+
params = params.to_hash
|
19
|
+
params = params.map do |key, value|
|
20
|
+
key = key.to_s if key.kind_of?(Symbol)
|
21
|
+
[key, value]
|
22
|
+
end
|
23
|
+
# Useful default for OAuth and caching.
|
24
|
+
# Only to be used for non-Array inputs. Arrays should preserve order.
|
25
|
+
params.sort!
|
26
|
+
end
|
27
|
+
|
28
|
+
# Helper lambda
|
29
|
+
to_query = lambda do |parent, value|
|
30
|
+
if value.is_a?(Hash)
|
31
|
+
value = value.map do |key, val|
|
32
|
+
key = escape(key)
|
33
|
+
[key, val]
|
34
|
+
end
|
35
|
+
value.sort!
|
36
|
+
buffer = ""
|
37
|
+
value.each do |key, val|
|
38
|
+
new_parent = "#{parent}%5B#{key}%5D"
|
39
|
+
buffer << "#{to_query.call(new_parent, val)}&"
|
40
|
+
end
|
41
|
+
return buffer.chop
|
42
|
+
elsif value.is_a?(Array)
|
43
|
+
new_parent = "#{parent}%5B%5D"
|
44
|
+
return new_parent if value.empty?
|
45
|
+
buffer = ""
|
46
|
+
value.each_with_index do |val, i|
|
47
|
+
buffer << "#{to_query.call(new_parent, val)}&"
|
48
|
+
end
|
49
|
+
return buffer.chop
|
50
|
+
elsif value.nil?
|
51
|
+
return parent
|
52
|
+
else
|
53
|
+
encoded_value = escape(value)
|
54
|
+
return "#{parent}=#{encoded_value}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# The params have form [['key1', 'value1'], ['key2', 'value2']].
|
59
|
+
buffer = ''
|
60
|
+
params.each do |parent, value|
|
61
|
+
encoded_parent = escape(parent)
|
62
|
+
buffer << "#{to_query.call(encoded_parent, value)}&"
|
63
|
+
end
|
64
|
+
return buffer.chop
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.decode(query)
|
68
|
+
return nil if query == nil
|
69
|
+
|
70
|
+
params = {}
|
71
|
+
query.split("&").each do |pair|
|
72
|
+
next if pair.empty?
|
73
|
+
key, value = pair.split("=", 2)
|
74
|
+
key = unescape(key)
|
75
|
+
value = unescape(value.gsub(/\+/, ' ')) if value
|
76
|
+
|
77
|
+
subkeys = key.scan(/[^\[\]]+(?:\]?\[\])?/)
|
78
|
+
context = params
|
79
|
+
subkeys.each_with_index do |subkey, i|
|
80
|
+
is_array = subkey =~ /[\[\]]+\Z/
|
81
|
+
subkey = $` if is_array
|
82
|
+
last_subkey = i == subkeys.length - 1
|
83
|
+
|
84
|
+
if !last_subkey || is_array
|
85
|
+
value_type = is_array ? Array : Hash
|
86
|
+
if context[subkey] && !context[subkey].is_a?(value_type)
|
87
|
+
raise TypeError, "expected %s (got %s) for param `%s'" % [
|
88
|
+
value_type.name,
|
89
|
+
context[subkey].class.name,
|
90
|
+
subkey
|
91
|
+
]
|
92
|
+
end
|
93
|
+
context = (context[subkey] ||= value_type.new)
|
94
|
+
end
|
95
|
+
|
96
|
+
if context.is_a?(Array) && !is_array
|
97
|
+
if !context.last.is_a?(Hash) || context.last.has_key?(subkey)
|
98
|
+
context << {}
|
99
|
+
end
|
100
|
+
context = context.last
|
101
|
+
end
|
102
|
+
|
103
|
+
if last_subkey
|
104
|
+
if is_array
|
105
|
+
context << value
|
106
|
+
else
|
107
|
+
context[subkey] = value
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
dehash(params, 0)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Internal: convert a nested hash with purely numeric keys into an array.
|
117
|
+
# FIXME: this is not compatible with Rack::Utils.parse_nested_query
|
118
|
+
def self.dehash(hash, depth)
|
119
|
+
hash.each do |key, value|
|
120
|
+
hash[key] = dehash(value, depth + 1) if value.kind_of?(Hash)
|
121
|
+
end
|
122
|
+
|
123
|
+
if depth > 0 && !hash.empty? && hash.keys.all? { |k| k =~ /^\d+$/ }
|
124
|
+
hash.keys.sort.inject([]) { |all, key| all << hash[key] }
|
125
|
+
else
|
126
|
+
hash
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
module FlatParamsEncoder
|
132
|
+
class << self
|
133
|
+
extend Forwardable
|
134
|
+
def_delegators :'Faraday::Utils', :escape, :unescape
|
135
|
+
end
|
136
|
+
|
137
|
+
def self.encode(params)
|
138
|
+
return nil if params == nil
|
139
|
+
|
140
|
+
if !params.is_a?(Array)
|
141
|
+
if !params.respond_to?(:to_hash)
|
142
|
+
raise TypeError,
|
143
|
+
"Can't convert #{params.class} into Hash."
|
144
|
+
end
|
145
|
+
params = params.to_hash
|
146
|
+
params = params.map do |key, value|
|
147
|
+
key = key.to_s if key.kind_of?(Symbol)
|
148
|
+
[key, value]
|
149
|
+
end
|
150
|
+
# Useful default for OAuth and caching.
|
151
|
+
# Only to be used for non-Array inputs. Arrays should preserve order.
|
152
|
+
params.sort!
|
153
|
+
end
|
154
|
+
|
155
|
+
# The params have form [['key1', 'value1'], ['key2', 'value2']].
|
156
|
+
buffer = ''
|
157
|
+
params.each do |key, value|
|
158
|
+
encoded_key = escape(key)
|
159
|
+
value = value.to_s if value == true || value == false
|
160
|
+
if value == nil
|
161
|
+
buffer << "#{encoded_key}&"
|
162
|
+
elsif value.kind_of?(Array)
|
163
|
+
value.each do |sub_value|
|
164
|
+
encoded_value = escape(sub_value)
|
165
|
+
buffer << "#{encoded_key}=#{encoded_value}&"
|
166
|
+
end
|
167
|
+
else
|
168
|
+
encoded_value = escape(value)
|
169
|
+
buffer << "#{encoded_key}=#{encoded_value}&"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
return buffer.chop
|
173
|
+
end
|
174
|
+
|
175
|
+
def self.decode(query)
|
176
|
+
empty_accumulator = {}
|
177
|
+
return nil if query == nil
|
178
|
+
split_query = (query.split('&').map do |pair|
|
179
|
+
pair.split('=', 2) if pair && !pair.empty?
|
180
|
+
end).compact
|
181
|
+
return split_query.inject(empty_accumulator.dup) do |accu, pair|
|
182
|
+
pair[0] = unescape(pair[0])
|
183
|
+
pair[1] = true if pair[1].nil?
|
184
|
+
if pair[1].respond_to?(:to_str)
|
185
|
+
pair[1] = unescape(pair[1].to_str.gsub(/\+/, " "))
|
186
|
+
end
|
187
|
+
if accu[pair[0]].kind_of?(Array)
|
188
|
+
accu[pair[0]] << pair[1]
|
189
|
+
elsif accu[pair[0]]
|
190
|
+
accu[pair[0]] = [accu[pair[0]], pair[1]]
|
191
|
+
else
|
192
|
+
accu[pair[0]] = pair[1]
|
193
|
+
end
|
194
|
+
accu
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
data/lib/faraday/rack_builder.rb
CHANGED
@@ -1,20 +1,12 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'faraday/adapter_registry'
|
4
|
-
|
5
1
|
module Faraday
|
6
2
|
# A Builder that processes requests into responses by passing through an inner
|
7
3
|
# middleware stack (heavily inspired by Rack).
|
8
4
|
#
|
9
|
-
#
|
10
|
-
# Faraday::Connection.new(url: 'http://sushi.com') do |builder|
|
5
|
+
# Faraday::Connection.new(:url => 'http://sushi.com') do |builder|
|
11
6
|
# builder.request :url_encoded # Faraday::Request::UrlEncoded
|
12
7
|
# builder.adapter :net_http # Faraday::Adapter::NetHttp
|
13
8
|
# end
|
14
9
|
class RackBuilder
|
15
|
-
# Used to detect missing arguments
|
16
|
-
NO_ARGUMENT = Object.new
|
17
|
-
|
18
10
|
attr_accessor :handlers
|
19
11
|
|
20
12
|
# Error raised when trying to modify the stack after calling `lock!`
|
@@ -23,28 +15,28 @@ module Faraday
|
|
23
15
|
# borrowed from ActiveSupport::Dependencies::Reference &
|
24
16
|
# ActionDispatch::MiddlewareStack::Middleware
|
25
17
|
class Handler
|
26
|
-
|
18
|
+
@@constants_mutex = Mutex.new
|
19
|
+
@@constants = Hash.new { |h, k|
|
20
|
+
value = k.respond_to?(:constantize) ? k.constantize : Object.const_get(k)
|
21
|
+
@@constants_mutex.synchronize { h[k] = value }
|
22
|
+
}
|
27
23
|
|
28
24
|
attr_reader :name
|
29
25
|
|
30
26
|
def initialize(klass, *args, &block)
|
31
27
|
@name = klass.to_s
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
def klass
|
38
|
-
REGISTRY.get(@name)
|
28
|
+
if klass.respond_to?(:name)
|
29
|
+
@@constants_mutex.synchronize { @@constants[@name] = klass }
|
30
|
+
end
|
31
|
+
@args, @block = args, block
|
39
32
|
end
|
40
33
|
|
41
|
-
def
|
42
|
-
|
43
|
-
end
|
34
|
+
def klass() @@constants[@name] end
|
35
|
+
def inspect() @name end
|
44
36
|
|
45
37
|
def ==(other)
|
46
38
|
if other.is_a? Handler
|
47
|
-
name == other.name
|
39
|
+
self.name == other.name
|
48
40
|
elsif other.respond_to? :name
|
49
41
|
klass == other
|
50
42
|
else
|
@@ -52,19 +44,18 @@ module Faraday
|
|
52
44
|
end
|
53
45
|
end
|
54
46
|
|
55
|
-
def build(app
|
47
|
+
def build(app)
|
56
48
|
klass.new(app, *@args, &@block)
|
57
49
|
end
|
58
50
|
end
|
59
51
|
|
60
|
-
def initialize(handlers = []
|
61
|
-
@adapter = adapter
|
52
|
+
def initialize(handlers = [])
|
62
53
|
@handlers = handlers
|
63
54
|
if block_given?
|
64
|
-
build(&
|
55
|
+
build(&Proc.new)
|
65
56
|
elsif @handlers.empty?
|
66
57
|
# default stack, if nothing else is configured
|
67
|
-
request :url_encoded
|
58
|
+
self.request :url_encoded
|
68
59
|
self.adapter Faraday.default_adapter
|
69
60
|
end
|
70
61
|
end
|
@@ -73,14 +64,13 @@ module Faraday
|
|
73
64
|
raise_if_locked
|
74
65
|
@handlers.clear unless options[:keep]
|
75
66
|
yield(self) if block_given?
|
76
|
-
adapter(Faraday.default_adapter) unless @adapter
|
77
67
|
end
|
78
68
|
|
79
69
|
def [](idx)
|
80
70
|
@handlers[idx]
|
81
71
|
end
|
82
72
|
|
83
|
-
# Locks the middleware stack to ensure no further modifications are
|
73
|
+
# Locks the middleware stack to ensure no further modifications are possible.
|
84
74
|
def lock!
|
85
75
|
@handlers.freeze
|
86
76
|
end
|
@@ -94,7 +84,7 @@ module Faraday
|
|
94
84
|
use_symbol(Faraday::Middleware, klass, *args, &block)
|
95
85
|
else
|
96
86
|
raise_if_locked
|
97
|
-
|
87
|
+
warn_middleware_after_adapter if adapter_set?
|
98
88
|
@handlers << self.class::Handler.new(klass, *args, &block)
|
99
89
|
end
|
100
90
|
end
|
@@ -107,11 +97,8 @@ module Faraday
|
|
107
97
|
use_symbol(Faraday::Response, key, *args, &block)
|
108
98
|
end
|
109
99
|
|
110
|
-
def adapter(
|
111
|
-
|
112
|
-
|
113
|
-
klass = Faraday::Adapter.lookup_middleware(klass) if klass.is_a?(Symbol)
|
114
|
-
@adapter = self.class::Handler.new(klass, *args, &block)
|
100
|
+
def adapter(key, *args, &block)
|
101
|
+
use_symbol(Faraday::Adapter, key, *args, &block)
|
115
102
|
end
|
116
103
|
|
117
104
|
## methods to push onto the various positions in the stack:
|
@@ -119,11 +106,12 @@ module Faraday
|
|
119
106
|
def insert(index, *args, &block)
|
120
107
|
raise_if_locked
|
121
108
|
index = assert_index(index)
|
109
|
+
warn_middleware_after_adapter if inserting_after_adapter?(index)
|
122
110
|
handler = self.class::Handler.new(*args, &block)
|
123
111
|
@handlers.insert(index, handler)
|
124
112
|
end
|
125
113
|
|
126
|
-
|
114
|
+
alias_method :insert_before, :insert
|
127
115
|
|
128
116
|
def insert_after(index, *args, &block)
|
129
117
|
index = assert_index(index)
|
@@ -145,11 +133,13 @@ module Faraday
|
|
145
133
|
# Processes a Request into a Response by passing it through this Builder's
|
146
134
|
# middleware stack.
|
147
135
|
#
|
148
|
-
#
|
149
|
-
#
|
136
|
+
# connection - Faraday::Connection
|
137
|
+
# request - Faraday::Request
|
150
138
|
#
|
151
|
-
#
|
139
|
+
# Returns a Faraday::Response.
|
152
140
|
def build_response(connection, request)
|
141
|
+
warn 'WARNING: No adapter was configured for this request' unless adapter_set?
|
142
|
+
|
153
143
|
app.call(build_env(connection, request))
|
154
144
|
end
|
155
145
|
|
@@ -163,26 +153,26 @@ module Faraday
|
|
163
153
|
def app
|
164
154
|
@app ||= begin
|
165
155
|
lock!
|
166
|
-
to_app
|
156
|
+
to_app(lambda { |env|
|
157
|
+
response = Response.new
|
158
|
+
env.response = response
|
159
|
+
response.finish(env) unless env.parallel?
|
160
|
+
response
|
161
|
+
})
|
167
162
|
end
|
168
163
|
end
|
169
164
|
|
170
|
-
def to_app
|
165
|
+
def to_app(inner_app)
|
171
166
|
# last added handler is the deepest and thus closest to the inner app
|
172
|
-
|
173
|
-
@handlers.reverse.inject(@adapter.build) do |app, handler|
|
174
|
-
handler.build(app)
|
175
|
-
end
|
167
|
+
@handlers.reverse.inject(inner_app) { |app, handler| handler.build(app) }
|
176
168
|
end
|
177
169
|
|
178
170
|
def ==(other)
|
179
|
-
other.is_a?(self.class) &&
|
180
|
-
@handlers == other.handlers &&
|
181
|
-
@adapter == other.adapter
|
171
|
+
other.is_a?(self.class) && @handlers == other.handlers
|
182
172
|
end
|
183
173
|
|
184
174
|
def dup
|
185
|
-
self.class.new(@handlers.dup
|
175
|
+
self.class.new(@handlers.dup)
|
186
176
|
end
|
187
177
|
|
188
178
|
# ENV Keys
|
@@ -202,36 +192,36 @@ module Faraday
|
|
202
192
|
# :password - Proxy server password
|
203
193
|
# :ssl - Hash of options for configuring SSL requests.
|
204
194
|
def build_env(connection, request)
|
205
|
-
|
206
|
-
request.path, request.params,
|
207
|
-
request.options.
|
208
|
-
|
209
|
-
|
210
|
-
Env.new(request.method, request.body, exclusive_url,
|
211
|
-
request.options, request.headers, connection.ssl,
|
212
|
-
connection.parallel_manager)
|
195
|
+
Env.new(request.method, request.body,
|
196
|
+
connection.build_exclusive_url(request.path, request.params, request.options.params_encoder),
|
197
|
+
request.options, request.headers, connection.ssl,
|
198
|
+
connection.parallel_manager)
|
213
199
|
end
|
214
200
|
|
215
201
|
private
|
216
202
|
|
217
|
-
LOCK_ERR = "can't modify middleware stack after making a request"
|
218
|
-
|
219
203
|
def raise_if_locked
|
220
|
-
raise StackLocked,
|
204
|
+
raise StackLocked, "can't modify middleware stack after making a request" if locked?
|
221
205
|
end
|
222
206
|
|
223
|
-
def
|
224
|
-
|
225
|
-
|
226
|
-
raise 'Adapter should be set using the `adapter` method, not `use`'
|
207
|
+
def warn_middleware_after_adapter
|
208
|
+
warn "WARNING: Unexpected middleware set after the adapter. " \
|
209
|
+
"This won't be supported from Faraday 1.0."
|
227
210
|
end
|
228
211
|
|
229
212
|
def adapter_set?
|
230
|
-
|
213
|
+
@handlers.any? { |handler| is_adapter?(handler) }
|
231
214
|
end
|
232
215
|
|
233
|
-
def
|
234
|
-
|
216
|
+
def inserting_after_adapter?(index)
|
217
|
+
adapter_index = @handlers.find_index { |handler| is_adapter?(handler) }
|
218
|
+
return false if adapter_index.nil?
|
219
|
+
|
220
|
+
index > adapter_index
|
221
|
+
end
|
222
|
+
|
223
|
+
def is_adapter?(handler)
|
224
|
+
handler.klass.ancestors.include? Faraday::Adapter
|
235
225
|
end
|
236
226
|
|
237
227
|
def use_symbol(mod, key, *args, &block)
|
@@ -241,7 +231,6 @@ module Faraday
|
|
241
231
|
def assert_index(index)
|
242
232
|
idx = index.is_a?(Integer) ? index : @handlers.index(index)
|
243
233
|
raise "No such handler: #{index.inspect}" unless idx
|
244
|
-
|
245
234
|
idx
|
246
235
|
end
|
247
236
|
end
|