faraday 0.11.0 → 1.4.3
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 +5 -5
- data/CHANGELOG.md +380 -0
- data/LICENSE.md +1 -1
- data/README.md +25 -229
- data/Rakefile +7 -0
- data/examples/client_spec.rb +65 -0
- data/examples/client_test.rb +79 -0
- data/lib/faraday/adapter/httpclient.rb +83 -59
- data/lib/faraday/adapter/patron.rb +92 -36
- data/lib/faraday/adapter/rack.rb +30 -13
- data/lib/faraday/adapter/test.rb +103 -62
- data/lib/faraday/adapter/typhoeus.rb +7 -115
- data/lib/faraday/adapter.rb +77 -22
- data/lib/faraday/adapter_registry.rb +30 -0
- data/lib/faraday/autoload.rb +42 -36
- data/lib/faraday/connection.rb +351 -167
- data/lib/faraday/dependency_loader.rb +37 -0
- data/lib/faraday/encoders/flat_params_encoder.rb +105 -0
- data/lib/faraday/encoders/nested_params_encoder.rb +176 -0
- data/lib/faraday/error.rb +127 -38
- data/lib/faraday/file_part.rb +128 -0
- data/lib/faraday/logging/formatter.rb +105 -0
- data/lib/faraday/methods.rb +6 -0
- data/lib/faraday/middleware.rb +19 -25
- data/lib/faraday/middleware_registry.rb +129 -0
- data/lib/faraday/options/connection_options.rb +22 -0
- data/lib/faraday/options/env.rb +181 -0
- data/lib/faraday/options/proxy_options.rb +32 -0
- data/lib/faraday/options/request_options.rb +22 -0
- data/lib/faraday/options/ssl_options.rb +59 -0
- data/lib/faraday/options.rb +58 -207
- data/lib/faraday/param_part.rb +53 -0
- data/lib/faraday/parameters.rb +4 -196
- data/lib/faraday/rack_builder.rb +84 -48
- data/lib/faraday/request/authorization.rb +44 -30
- data/lib/faraday/request/basic_authentication.rb +14 -7
- data/lib/faraday/request/instrumentation.rb +45 -27
- data/lib/faraday/request/multipart.rb +88 -45
- data/lib/faraday/request/retry.rb +211 -126
- data/lib/faraday/request/token_authentication.rb +15 -10
- data/lib/faraday/request/url_encoded.rb +43 -23
- data/lib/faraday/request.rb +94 -32
- data/lib/faraday/response/logger.rb +22 -69
- data/lib/faraday/response/raise_error.rb +49 -14
- data/lib/faraday/response.rb +27 -23
- data/lib/faraday/utils/headers.rb +139 -0
- data/lib/faraday/utils/params_hash.rb +61 -0
- data/lib/faraday/utils.rb +38 -238
- data/lib/faraday/version.rb +5 -0
- data/lib/faraday.rb +124 -187
- data/spec/external_adapters/faraday_specs_setup.rb +14 -0
- data/spec/faraday/adapter/em_http_spec.rb +47 -0
- data/spec/faraday/adapter/em_synchrony_spec.rb +16 -0
- data/spec/faraday/adapter/excon_spec.rb +49 -0
- data/spec/faraday/adapter/httpclient_spec.rb +73 -0
- data/spec/faraday/adapter/net_http_spec.rb +64 -0
- data/spec/faraday/adapter/patron_spec.rb +18 -0
- data/spec/faraday/adapter/rack_spec.rb +8 -0
- data/spec/faraday/adapter/test_spec.rb +260 -0
- data/spec/faraday/adapter/typhoeus_spec.rb +7 -0
- data/spec/faraday/adapter_registry_spec.rb +28 -0
- data/spec/faraday/adapter_spec.rb +55 -0
- data/spec/faraday/composite_read_io_spec.rb +80 -0
- data/spec/faraday/connection_spec.rb +736 -0
- data/spec/faraday/error_spec.rb +60 -0
- data/spec/faraday/middleware_spec.rb +52 -0
- data/spec/faraday/options/env_spec.rb +70 -0
- data/spec/faraday/options/options_spec.rb +297 -0
- data/spec/faraday/options/proxy_options_spec.rb +44 -0
- data/spec/faraday/options/request_options_spec.rb +19 -0
- data/spec/faraday/params_encoders/flat_spec.rb +42 -0
- data/spec/faraday/params_encoders/nested_spec.rb +142 -0
- data/spec/faraday/rack_builder_spec.rb +345 -0
- data/spec/faraday/request/authorization_spec.rb +88 -0
- data/spec/faraday/request/instrumentation_spec.rb +76 -0
- data/spec/faraday/request/multipart_spec.rb +302 -0
- data/spec/faraday/request/retry_spec.rb +242 -0
- data/spec/faraday/request/url_encoded_spec.rb +83 -0
- data/spec/faraday/request_spec.rb +120 -0
- data/spec/faraday/response/logger_spec.rb +220 -0
- data/spec/faraday/response/middleware_spec.rb +68 -0
- data/spec/faraday/response/raise_error_spec.rb +169 -0
- data/spec/faraday/response_spec.rb +75 -0
- data/spec/faraday/utils/headers_spec.rb +82 -0
- data/spec/faraday/utils_spec.rb +56 -0
- data/spec/faraday_spec.rb +37 -0
- data/spec/spec_helper.rb +132 -0
- data/spec/support/disabling_stub.rb +14 -0
- data/spec/support/fake_safe_buffer.rb +15 -0
- data/spec/support/helper_methods.rb +133 -0
- data/spec/support/shared_examples/adapter.rb +105 -0
- data/spec/support/shared_examples/params_encoder.rb +18 -0
- data/spec/support/shared_examples/request_method.rb +262 -0
- data/spec/support/streaming_response_checker.rb +35 -0
- data/spec/support/webmock_rack_app.rb +68 -0
- metadata +164 -16
- data/lib/faraday/adapter/em_http.rb +0 -243
- data/lib/faraday/adapter/em_http_ssl_patch.rb +0 -56
- data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +0 -66
- data/lib/faraday/adapter/em_synchrony.rb +0 -106
- data/lib/faraday/adapter/excon.rb +0 -80
- data/lib/faraday/adapter/net_http.rb +0 -135
- data/lib/faraday/adapter/net_http_persistent.rb +0 -50
- data/lib/faraday/upload_io.rb +0 -67
data/lib/faraday/options.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Faraday
|
2
4
|
# Subclasses Struct with some special helpers for converting from a Hash to
|
3
5
|
# a Struct.
|
@@ -10,6 +12,7 @@ module Faraday
|
|
10
12
|
# Public
|
11
13
|
def each
|
12
14
|
return to_enum(:each) unless block_given?
|
15
|
+
|
13
16
|
members.each do |key|
|
14
17
|
yield(key.to_sym, send(key))
|
15
18
|
end
|
@@ -18,23 +21,20 @@ module Faraday
|
|
18
21
|
# Public
|
19
22
|
def update(obj)
|
20
23
|
obj.each do |key, value|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
value.
|
26
|
-
|
27
|
-
|
28
|
-
value = hash
|
24
|
+
sub_options = self.class.options_for(key)
|
25
|
+
if sub_options
|
26
|
+
new_value = sub_options.from(value) if value
|
27
|
+
elsif value.is_a?(Hash)
|
28
|
+
new_value = value.dup
|
29
|
+
else
|
30
|
+
new_value = value
|
29
31
|
end
|
30
32
|
|
31
|
-
|
33
|
+
send("#{key}=", new_value) unless new_value.nil?
|
32
34
|
end
|
33
35
|
self
|
34
36
|
end
|
35
37
|
|
36
|
-
alias merge! update
|
37
|
-
|
38
38
|
# Public
|
39
39
|
def delete(key)
|
40
40
|
value = send(key)
|
@@ -48,25 +48,38 @@ module Faraday
|
|
48
48
|
end
|
49
49
|
|
50
50
|
# Public
|
51
|
-
def merge(
|
52
|
-
|
51
|
+
def merge!(other)
|
52
|
+
other.each do |key, other_value|
|
53
|
+
self_value = send(key)
|
54
|
+
sub_options = self.class.options_for(key)
|
55
|
+
new_value = if self_value && sub_options && other_value
|
56
|
+
self_value.merge(other_value)
|
57
|
+
else
|
58
|
+
other_value
|
59
|
+
end
|
60
|
+
send("#{key}=", new_value) unless new_value.nil?
|
61
|
+
end
|
62
|
+
self
|
53
63
|
end
|
54
|
-
|
64
|
+
|
55
65
|
# Public
|
56
|
-
def
|
66
|
+
def merge(other)
|
67
|
+
dup.merge!(other)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Public
|
71
|
+
def deep_dup
|
57
72
|
self.class.from(self)
|
58
73
|
end
|
59
74
|
|
60
|
-
alias clone dup
|
61
|
-
|
62
75
|
# Public
|
63
76
|
def fetch(key, *args)
|
64
77
|
unless symbolized_key_set.include?(key.to_sym)
|
65
78
|
key_setter = "#{key}="
|
66
|
-
if args.
|
79
|
+
if !args.empty?
|
67
80
|
send(key_setter, args.first)
|
68
81
|
elsif block_given?
|
69
|
-
send(key_setter,
|
82
|
+
send(key_setter, yield(key))
|
70
83
|
else
|
71
84
|
raise self.class.fetch_error_class, "key not found: #{key.inspect}"
|
72
85
|
end
|
@@ -90,11 +103,10 @@ module Faraday
|
|
90
103
|
end
|
91
104
|
|
92
105
|
# Public
|
93
|
-
def each_key
|
106
|
+
def each_key(&block)
|
94
107
|
return to_enum(:each_key) unless block_given?
|
95
|
-
|
96
|
-
|
97
|
-
end
|
108
|
+
|
109
|
+
keys.each(&block)
|
98
110
|
end
|
99
111
|
|
100
112
|
# Public
|
@@ -105,11 +117,10 @@ module Faraday
|
|
105
117
|
alias has_key? key?
|
106
118
|
|
107
119
|
# Public
|
108
|
-
def each_value
|
120
|
+
def each_value(&block)
|
109
121
|
return to_enum(:each_value) unless block_given?
|
110
|
-
|
111
|
-
|
112
|
-
end
|
122
|
+
|
123
|
+
values.each(&block)
|
113
124
|
end
|
114
125
|
|
115
126
|
# Public
|
@@ -136,9 +147,9 @@ module Faraday
|
|
136
147
|
value = send(member)
|
137
148
|
values << "#{member}=#{value.inspect}" if value
|
138
149
|
end
|
139
|
-
values = values.empty? ? '
|
150
|
+
values = values.empty? ? '(empty)' : values.join(', ')
|
140
151
|
|
141
|
-
%(#<#{self.class}#{values}>)
|
152
|
+
%(#<#{self.class} #{values}>)
|
142
153
|
end
|
143
154
|
|
144
155
|
# Internal
|
@@ -156,8 +167,12 @@ module Faraday
|
|
156
167
|
@attribute_options ||= {}
|
157
168
|
end
|
158
169
|
|
159
|
-
def self.memoized(key)
|
160
|
-
|
170
|
+
def self.memoized(key, &block)
|
171
|
+
unless block_given?
|
172
|
+
raise ArgumentError, '#memoized must be called with a block'
|
173
|
+
end
|
174
|
+
|
175
|
+
memoized_attributes[key.to_sym] = block
|
161
176
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
162
177
|
def #{key}() self[:#{key}]; end
|
163
178
|
RUBY
|
@@ -169,7 +184,7 @@ module Faraday
|
|
169
184
|
|
170
185
|
def [](key)
|
171
186
|
key = key.to_sym
|
172
|
-
if method = self.class.memoized_attributes[key]
|
187
|
+
if (method = self.class.memoized_attributes[key])
|
173
188
|
super(key) || (self[key] = instance_eval(&method))
|
174
189
|
else
|
175
190
|
super
|
@@ -177,7 +192,7 @@ module Faraday
|
|
177
192
|
end
|
178
193
|
|
179
194
|
def symbolized_key_set
|
180
|
-
@symbolized_key_set ||= Set.new(keys.map
|
195
|
+
@symbolized_key_set ||= Set.new(keys.map(&:to_sym))
|
181
196
|
end
|
182
197
|
|
183
198
|
def self.inherited(subclass)
|
@@ -188,180 +203,16 @@ module Faraday
|
|
188
203
|
|
189
204
|
def self.fetch_error_class
|
190
205
|
@fetch_error_class ||= if Object.const_defined?(:KeyError)
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
class RequestOptions < Options.new(:params_encoder, :proxy, :bind,
|
199
|
-
:timeout, :open_timeout, :boundary,
|
200
|
-
:oauth)
|
201
|
-
|
202
|
-
def []=(key, value)
|
203
|
-
if key && key.to_sym == :proxy
|
204
|
-
super(key, value ? ProxyOptions.from(value) : nil)
|
205
|
-
else
|
206
|
-
super(key, value)
|
207
|
-
end
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
class SSLOptions < Options.new(:verify, :ca_file, :ca_path, :verify_mode,
|
212
|
-
:cert_store, :client_cert, :client_key, :certificate, :private_key, :verify_depth, :version)
|
213
|
-
|
214
|
-
def verify?
|
215
|
-
verify != false
|
216
|
-
end
|
217
|
-
|
218
|
-
def disable?
|
219
|
-
!verify?
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
class ProxyOptions < Options.new(:uri, :user, :password)
|
224
|
-
extend Forwardable
|
225
|
-
def_delegators :uri, :scheme, :scheme=, :host, :host=, :port, :port=, :path, :path=
|
226
|
-
|
227
|
-
def self.from(value)
|
228
|
-
case value
|
229
|
-
when String
|
230
|
-
value = {:uri => Utils.URI(value)}
|
231
|
-
when URI
|
232
|
-
value = {:uri => value}
|
233
|
-
when Hash, Options
|
234
|
-
if uri = value.delete(:uri)
|
235
|
-
value[:uri] = Utils.URI(uri)
|
236
|
-
end
|
237
|
-
end
|
238
|
-
super(value)
|
239
|
-
end
|
240
|
-
|
241
|
-
memoized(:user) { uri.user && Utils.unescape(uri.user) }
|
242
|
-
memoized(:password) { uri.password && Utils.unescape(uri.password) }
|
243
|
-
end
|
244
|
-
|
245
|
-
class ConnectionOptions < Options.new(:request, :proxy, :ssl, :builder, :url,
|
246
|
-
:parallel_manager, :params, :headers, :builder_class)
|
247
|
-
|
248
|
-
options :request => RequestOptions, :ssl => SSLOptions
|
249
|
-
|
250
|
-
memoized(:request) { self.class.options_for(:request).new }
|
251
|
-
|
252
|
-
memoized(:ssl) { self.class.options_for(:ssl).new }
|
253
|
-
|
254
|
-
memoized(:builder_class) { RackBuilder }
|
255
|
-
|
256
|
-
def new_builder(block)
|
257
|
-
builder_class.new(&block)
|
258
|
-
end
|
259
|
-
end
|
260
|
-
|
261
|
-
class Env < Options.new(:method, :body, :url, :request, :request_headers,
|
262
|
-
:ssl, :parallel_manager, :params, :response, :response_headers, :status,
|
263
|
-
:reason_phrase)
|
264
|
-
|
265
|
-
ContentLength = 'Content-Length'.freeze
|
266
|
-
StatusesWithoutBody = Set.new [204, 304]
|
267
|
-
SuccessfulStatuses = 200..299
|
268
|
-
|
269
|
-
# A Set of HTTP verbs that typically send a body. If no body is set for
|
270
|
-
# these requests, the Content-Length header is set to 0.
|
271
|
-
MethodsWithBodies = Set.new [:post, :put, :patch, :options]
|
272
|
-
|
273
|
-
options :request => RequestOptions,
|
274
|
-
:request_headers => Utils::Headers, :response_headers => Utils::Headers
|
275
|
-
|
276
|
-
extend Forwardable
|
277
|
-
|
278
|
-
def_delegators :request, :params_encoder
|
279
|
-
|
280
|
-
# Public
|
281
|
-
def self.from(value)
|
282
|
-
env = super(value)
|
283
|
-
if value.respond_to?(:custom_members)
|
284
|
-
env.custom_members.update(value.custom_members)
|
285
|
-
end
|
286
|
-
env
|
287
|
-
end
|
288
|
-
|
289
|
-
# Public
|
290
|
-
def [](key)
|
291
|
-
if in_member_set?(key)
|
292
|
-
super(key)
|
293
|
-
else
|
294
|
-
custom_members[key]
|
295
|
-
end
|
296
|
-
end
|
297
|
-
|
298
|
-
# Public
|
299
|
-
def []=(key, value)
|
300
|
-
if in_member_set?(key)
|
301
|
-
super(key, value)
|
302
|
-
else
|
303
|
-
custom_members[key] = value
|
304
|
-
end
|
305
|
-
end
|
306
|
-
|
307
|
-
# Public
|
308
|
-
def success?
|
309
|
-
SuccessfulStatuses.include?(status)
|
310
|
-
end
|
311
|
-
|
312
|
-
# Public
|
313
|
-
def needs_body?
|
314
|
-
!body && MethodsWithBodies.include?(method)
|
315
|
-
end
|
316
|
-
|
317
|
-
# Public
|
318
|
-
def clear_body
|
319
|
-
request_headers[ContentLength] = '0'
|
320
|
-
self.body = ''
|
321
|
-
end
|
322
|
-
|
323
|
-
# Public
|
324
|
-
def parse_body?
|
325
|
-
!StatusesWithoutBody.include?(status)
|
326
|
-
end
|
327
|
-
|
328
|
-
# Public
|
329
|
-
def parallel?
|
330
|
-
!!parallel_manager
|
331
|
-
end
|
332
|
-
|
333
|
-
def inspect
|
334
|
-
attrs = [nil]
|
335
|
-
members.each do |mem|
|
336
|
-
if value = send(mem)
|
337
|
-
attrs << "@#{mem}=#{value.inspect}"
|
338
|
-
end
|
339
|
-
end
|
340
|
-
if !custom_members.empty?
|
341
|
-
attrs << "@custom=#{custom_members.inspect}"
|
342
|
-
end
|
343
|
-
%(#<#{self.class}#{attrs.join(" ")}>)
|
344
|
-
end
|
345
|
-
|
346
|
-
# Internal
|
347
|
-
def custom_members
|
348
|
-
@custom_members ||= {}
|
349
|
-
end
|
350
|
-
|
351
|
-
# Internal
|
352
|
-
if members.first.is_a?(Symbol)
|
353
|
-
def in_member_set?(key)
|
354
|
-
self.class.member_set.include?(key.to_sym)
|
355
|
-
end
|
356
|
-
else
|
357
|
-
def in_member_set?(key)
|
358
|
-
self.class.member_set.include?(key.to_s)
|
359
|
-
end
|
360
|
-
end
|
361
|
-
|
362
|
-
# Internal
|
363
|
-
def self.member_set
|
364
|
-
@member_set ||= Set.new(members)
|
206
|
+
::KeyError
|
207
|
+
else
|
208
|
+
::IndexError
|
209
|
+
end
|
365
210
|
end
|
366
211
|
end
|
367
212
|
end
|
213
|
+
|
214
|
+
require 'faraday/options/request_options'
|
215
|
+
require 'faraday/options/ssl_options'
|
216
|
+
require 'faraday/options/proxy_options'
|
217
|
+
require 'faraday/options/connection_options'
|
218
|
+
require 'faraday/options/env'
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Faraday
|
4
|
+
# Multipart value used to POST data with a content type.
|
5
|
+
class ParamPart
|
6
|
+
# @param value [String] Uploaded content as a String.
|
7
|
+
# @param content_type [String] String content type of the value.
|
8
|
+
# @param content_id [String] Optional String of this value's Content-ID.
|
9
|
+
#
|
10
|
+
# @return [Faraday::ParamPart]
|
11
|
+
def initialize(value, content_type, content_id = nil)
|
12
|
+
@value = value
|
13
|
+
@content_type = content_type
|
14
|
+
@content_id = content_id
|
15
|
+
end
|
16
|
+
|
17
|
+
# Converts this value to a form part.
|
18
|
+
#
|
19
|
+
# @param boundary [String] String multipart boundary that must not exist in
|
20
|
+
# the content exactly.
|
21
|
+
# @param key [String] String key name for this value.
|
22
|
+
#
|
23
|
+
# @return [Faraday::Parts::Part]
|
24
|
+
def to_part(boundary, key)
|
25
|
+
Faraday::Parts::Part.new(boundary, key, value, headers)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns a Hash of String key/value pairs.
|
29
|
+
#
|
30
|
+
# @return [Hash]
|
31
|
+
def headers
|
32
|
+
{
|
33
|
+
'Content-Type' => content_type,
|
34
|
+
'Content-ID' => content_id
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
# The content to upload.
|
39
|
+
#
|
40
|
+
# @return [String]
|
41
|
+
attr_reader :value
|
42
|
+
|
43
|
+
# The value's content type.
|
44
|
+
#
|
45
|
+
# @return [String]
|
46
|
+
attr_reader :content_type
|
47
|
+
|
48
|
+
# The value's content ID, if given.
|
49
|
+
#
|
50
|
+
# @return [String, nil]
|
51
|
+
attr_reader :content_id
|
52
|
+
end
|
53
|
+
end
|
data/lib/faraday/parameters.rb
CHANGED
@@ -1,197 +1,5 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
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
|
-
buffer = ""
|
44
|
-
value.each_with_index do |val, i|
|
45
|
-
new_parent = "#{parent}%5B%5D"
|
46
|
-
buffer << "#{to_query.call(new_parent, val)}&"
|
47
|
-
end
|
48
|
-
return buffer.chop
|
49
|
-
elsif value.nil?
|
50
|
-
return parent
|
51
|
-
else
|
52
|
-
encoded_value = escape(value)
|
53
|
-
return "#{parent}=#{encoded_value}"
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
# The params have form [['key1', 'value1'], ['key2', 'value2']].
|
58
|
-
buffer = ''
|
59
|
-
params.each do |parent, value|
|
60
|
-
encoded_parent = escape(parent)
|
61
|
-
buffer << "#{to_query.call(encoded_parent, value)}&"
|
62
|
-
end
|
63
|
-
return buffer.chop
|
64
|
-
end
|
65
|
-
|
66
|
-
def self.decode(query)
|
67
|
-
return nil if query == nil
|
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)
|
93
|
-
end
|
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
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
dehash(params, 0)
|
113
|
-
end
|
114
|
-
|
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
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
module FlatParamsEncoder
|
131
|
-
class << self
|
132
|
-
extend Forwardable
|
133
|
-
def_delegators :'Faraday::Utils', :escape, :unescape
|
134
|
-
end
|
135
|
-
|
136
|
-
def self.encode(params)
|
137
|
-
return nil if params == nil
|
138
|
-
|
139
|
-
if !params.is_a?(Array)
|
140
|
-
if !params.respond_to?(:to_hash)
|
141
|
-
raise TypeError,
|
142
|
-
"Can't convert #{params.class} into Hash."
|
143
|
-
end
|
144
|
-
params = params.to_hash
|
145
|
-
params = params.map do |key, value|
|
146
|
-
key = key.to_s if key.kind_of?(Symbol)
|
147
|
-
[key, value]
|
148
|
-
end
|
149
|
-
# Useful default for OAuth and caching.
|
150
|
-
# Only to be used for non-Array inputs. Arrays should preserve order.
|
151
|
-
params.sort!
|
152
|
-
end
|
153
|
-
|
154
|
-
# The params have form [['key1', 'value1'], ['key2', 'value2']].
|
155
|
-
buffer = ''
|
156
|
-
params.each do |key, value|
|
157
|
-
encoded_key = escape(key)
|
158
|
-
value = value.to_s if value == true || value == false
|
159
|
-
if value == nil
|
160
|
-
buffer << "#{encoded_key}&"
|
161
|
-
elsif value.kind_of?(Array)
|
162
|
-
value.each do |sub_value|
|
163
|
-
encoded_value = escape(sub_value)
|
164
|
-
buffer << "#{encoded_key}=#{encoded_value}&"
|
165
|
-
end
|
166
|
-
else
|
167
|
-
encoded_value = escape(value)
|
168
|
-
buffer << "#{encoded_key}=#{encoded_value}&"
|
169
|
-
end
|
170
|
-
end
|
171
|
-
return buffer.chop
|
172
|
-
end
|
173
|
-
|
174
|
-
def self.decode(query)
|
175
|
-
empty_accumulator = {}
|
176
|
-
return nil if query == nil
|
177
|
-
split_query = (query.split('&').map do |pair|
|
178
|
-
pair.split('=', 2) if pair && !pair.empty?
|
179
|
-
end).compact
|
180
|
-
return split_query.inject(empty_accumulator.dup) do |accu, pair|
|
181
|
-
pair[0] = unescape(pair[0])
|
182
|
-
pair[1] = true if pair[1].nil?
|
183
|
-
if pair[1].respond_to?(:to_str)
|
184
|
-
pair[1] = unescape(pair[1].to_str.gsub(/\+/, " "))
|
185
|
-
end
|
186
|
-
if accu[pair[0]].kind_of?(Array)
|
187
|
-
accu[pair[0]] << pair[1]
|
188
|
-
elsif accu[pair[0]]
|
189
|
-
accu[pair[0]] = [accu[pair[0]], pair[1]]
|
190
|
-
else
|
191
|
-
accu[pair[0]] = pair[1]
|
192
|
-
end
|
193
|
-
accu
|
194
|
-
end
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
3
|
+
require 'forwardable'
|
4
|
+
require 'faraday/encoders/nested_params_encoder'
|
5
|
+
require 'faraday/encoders/flat_params_encoder'
|