faraday 0.9.1 → 1.8.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 +5 -5
- data/CHANGELOG.md +360 -0
- data/LICENSE.md +1 -1
- data/README.md +28 -195
- data/Rakefile +4 -68
- data/examples/client_spec.rb +97 -0
- data/examples/client_test.rb +118 -0
- data/lib/faraday/adapter/test.rb +158 -58
- data/lib/faraday/adapter/typhoeus.rb +7 -115
- data/lib/faraday/adapter.rb +79 -20
- data/lib/faraday/adapter_registry.rb +30 -0
- data/lib/faraday/autoload.rb +39 -36
- data/lib/faraday/connection.rb +378 -168
- 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 +128 -29
- 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 +61 -193
- data/lib/faraday/param_part.rb +53 -0
- data/lib/faraday/parameters.rb +4 -180
- data/lib/faraday/rack_builder.rb +84 -47
- data/lib/faraday/request/authorization.rb +51 -31
- 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 +212 -121
- data/lib/faraday/request/token_authentication.rb +15 -10
- data/lib/faraday/request/url_encoded.rb +43 -23
- data/lib/faraday/request.rb +96 -32
- data/lib/faraday/response/logger.rb +22 -48
- data/lib/faraday/response/raise_error.rb +49 -14
- data/lib/faraday/response.rb +33 -25
- data/lib/faraday/utils/headers.rb +139 -0
- data/lib/faraday/utils/params_hash.rb +61 -0
- data/lib/faraday/utils.rb +38 -218
- data/lib/faraday/version.rb +5 -0
- data/lib/faraday.rb +130 -213
- data/spec/external_adapters/faraday_specs_setup.rb +14 -0
- data/spec/faraday/adapter/em_http_spec.rb +49 -0
- data/spec/faraday/adapter/em_synchrony_spec.rb +18 -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 +377 -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 +96 -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 +199 -98
- data/.document +0 -6
- data/CONTRIBUTING.md +0 -36
- data/Gemfile +0 -25
- data/faraday.gemspec +0 -34
- data/lib/faraday/adapter/em_http.rb +0 -237
- 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 -92
- data/lib/faraday/adapter/excon.rb +0 -80
- data/lib/faraday/adapter/httpclient.rb +0 -106
- data/lib/faraday/adapter/net_http.rb +0 -130
- data/lib/faraday/adapter/net_http_persistent.rb +0 -48
- data/lib/faraday/adapter/patron.rb +0 -72
- data/lib/faraday/adapter/rack.rb +0 -58
- data/lib/faraday/upload_io.rb +0 -67
- 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/lib/faraday/rack_builder.rb
CHANGED
@@ -1,12 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ruby2_keywords'
|
4
|
+
require 'faraday/adapter_registry'
|
5
|
+
|
1
6
|
module Faraday
|
2
7
|
# A Builder that processes requests into responses by passing through an inner
|
3
8
|
# middleware stack (heavily inspired by Rack).
|
4
9
|
#
|
5
|
-
#
|
10
|
+
# @example
|
11
|
+
# Faraday::Connection.new(url: 'http://sushi.com') do |builder|
|
6
12
|
# builder.request :url_encoded # Faraday::Request::UrlEncoded
|
7
13
|
# builder.adapter :net_http # Faraday::Adapter::NetHttp
|
8
14
|
# end
|
9
15
|
class RackBuilder
|
16
|
+
# Used to detect missing arguments
|
17
|
+
NO_ARGUMENT = Object.new
|
18
|
+
|
10
19
|
attr_accessor :handlers
|
11
20
|
|
12
21
|
# Error raised when trying to modify the stack after calling `lock!`
|
@@ -15,28 +24,28 @@ module Faraday
|
|
15
24
|
# borrowed from ActiveSupport::Dependencies::Reference &
|
16
25
|
# ActionDispatch::MiddlewareStack::Middleware
|
17
26
|
class Handler
|
18
|
-
|
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
|
+
REGISTRY = Faraday::AdapterRegistry.new
|
23
28
|
|
24
29
|
attr_reader :name
|
25
30
|
|
26
|
-
def initialize(klass, *args, &block)
|
31
|
+
ruby2_keywords def initialize(klass, *args, &block)
|
27
32
|
@name = klass.to_s
|
28
|
-
if klass.respond_to?(:name)
|
29
|
-
|
30
|
-
|
31
|
-
|
33
|
+
REGISTRY.set(klass) if klass.respond_to?(:name)
|
34
|
+
@args = args
|
35
|
+
@block = block
|
36
|
+
end
|
37
|
+
|
38
|
+
def klass
|
39
|
+
REGISTRY.get(@name)
|
32
40
|
end
|
33
41
|
|
34
|
-
def
|
35
|
-
|
42
|
+
def inspect
|
43
|
+
@name
|
44
|
+
end
|
36
45
|
|
37
46
|
def ==(other)
|
38
47
|
if other.is_a? Handler
|
39
|
-
|
48
|
+
name == other.name
|
40
49
|
elsif other.respond_to? :name
|
41
50
|
klass == other
|
42
51
|
else
|
@@ -44,18 +53,19 @@ module Faraday
|
|
44
53
|
end
|
45
54
|
end
|
46
55
|
|
47
|
-
def build(app)
|
56
|
+
def build(app = nil)
|
48
57
|
klass.new(app, *@args, &@block)
|
49
58
|
end
|
50
59
|
end
|
51
60
|
|
52
|
-
def initialize(handlers = [])
|
61
|
+
def initialize(handlers = [], adapter = nil, &block)
|
62
|
+
@adapter = adapter
|
53
63
|
@handlers = handlers
|
54
64
|
if block_given?
|
55
|
-
build(&
|
65
|
+
build(&block)
|
56
66
|
elsif @handlers.empty?
|
57
67
|
# default stack, if nothing else is configured
|
58
|
-
|
68
|
+
request :url_encoded
|
59
69
|
self.adapter Faraday.default_adapter
|
60
70
|
end
|
61
71
|
end
|
@@ -64,13 +74,14 @@ module Faraday
|
|
64
74
|
raise_if_locked
|
65
75
|
@handlers.clear unless options[:keep]
|
66
76
|
yield(self) if block_given?
|
77
|
+
adapter(Faraday.default_adapter) unless @adapter
|
67
78
|
end
|
68
79
|
|
69
80
|
def [](idx)
|
70
81
|
@handlers[idx]
|
71
82
|
end
|
72
83
|
|
73
|
-
# Locks the middleware stack to ensure no further modifications are
|
84
|
+
# Locks the middleware stack to ensure no further modifications are made.
|
74
85
|
def lock!
|
75
86
|
@handlers.freeze
|
76
87
|
end
|
@@ -79,44 +90,48 @@ module Faraday
|
|
79
90
|
@handlers.frozen?
|
80
91
|
end
|
81
92
|
|
82
|
-
def use(klass, *args, &block)
|
93
|
+
ruby2_keywords def use(klass, *args, &block)
|
83
94
|
if klass.is_a? Symbol
|
84
95
|
use_symbol(Faraday::Middleware, klass, *args, &block)
|
85
96
|
else
|
86
97
|
raise_if_locked
|
98
|
+
raise_if_adapter(klass)
|
87
99
|
@handlers << self.class::Handler.new(klass, *args, &block)
|
88
100
|
end
|
89
101
|
end
|
90
102
|
|
91
|
-
def request(key, *args, &block)
|
103
|
+
ruby2_keywords def request(key, *args, &block)
|
92
104
|
use_symbol(Faraday::Request, key, *args, &block)
|
93
105
|
end
|
94
106
|
|
95
|
-
def response(key, *args, &block)
|
107
|
+
ruby2_keywords def response(key, *args, &block)
|
96
108
|
use_symbol(Faraday::Response, key, *args, &block)
|
97
109
|
end
|
98
110
|
|
99
|
-
def adapter(
|
100
|
-
|
111
|
+
ruby2_keywords def adapter(klass = NO_ARGUMENT, *args, &block)
|
112
|
+
return @adapter if klass == NO_ARGUMENT
|
113
|
+
|
114
|
+
klass = Faraday::Adapter.lookup_middleware(klass) if klass.is_a?(Symbol)
|
115
|
+
@adapter = self.class::Handler.new(klass, *args, &block)
|
101
116
|
end
|
102
117
|
|
103
118
|
## methods to push onto the various positions in the stack:
|
104
119
|
|
105
|
-
def insert(index, *args, &block)
|
120
|
+
ruby2_keywords def insert(index, *args, &block)
|
106
121
|
raise_if_locked
|
107
122
|
index = assert_index(index)
|
108
123
|
handler = self.class::Handler.new(*args, &block)
|
109
124
|
@handlers.insert(index, handler)
|
110
125
|
end
|
111
126
|
|
112
|
-
|
127
|
+
alias insert_before insert
|
113
128
|
|
114
|
-
def insert_after(index, *args, &block)
|
129
|
+
ruby2_keywords def insert_after(index, *args, &block)
|
115
130
|
index = assert_index(index)
|
116
131
|
insert(index + 1, *args, &block)
|
117
132
|
end
|
118
133
|
|
119
|
-
def swap(index, *args, &block)
|
134
|
+
ruby2_keywords def swap(index, *args, &block)
|
120
135
|
raise_if_locked
|
121
136
|
index = assert_index(index)
|
122
137
|
@handlers.delete_at(index)
|
@@ -131,10 +146,10 @@ module Faraday
|
|
131
146
|
# Processes a Request into a Response by passing it through this Builder's
|
132
147
|
# middleware stack.
|
133
148
|
#
|
134
|
-
# connection
|
135
|
-
# request
|
149
|
+
# @param connection [Faraday::Connection]
|
150
|
+
# @param request [Faraday::Request]
|
136
151
|
#
|
137
|
-
#
|
152
|
+
# @return [Faraday::Response]
|
138
153
|
def build_response(connection, request)
|
139
154
|
app.call(build_env(connection, request))
|
140
155
|
end
|
@@ -149,29 +164,30 @@ module Faraday
|
|
149
164
|
def app
|
150
165
|
@app ||= begin
|
151
166
|
lock!
|
152
|
-
to_app
|
153
|
-
response = Response.new
|
154
|
-
response.finish(env) unless env.parallel?
|
155
|
-
env.response = response
|
156
|
-
})
|
167
|
+
to_app
|
157
168
|
end
|
158
169
|
end
|
159
170
|
|
160
|
-
def to_app
|
171
|
+
def to_app
|
161
172
|
# last added handler is the deepest and thus closest to the inner app
|
162
|
-
|
173
|
+
# adapter is always the last one
|
174
|
+
@handlers.reverse.inject(@adapter.build) do |app, handler|
|
175
|
+
handler.build(app)
|
176
|
+
end
|
163
177
|
end
|
164
178
|
|
165
179
|
def ==(other)
|
166
|
-
other.is_a?(self.class) &&
|
180
|
+
other.is_a?(self.class) &&
|
181
|
+
@handlers == other.handlers &&
|
182
|
+
@adapter == other.adapter
|
167
183
|
end
|
168
184
|
|
169
185
|
def dup
|
170
|
-
self.class.new(@handlers.dup)
|
186
|
+
self.class.new(@handlers.dup, @adapter.dup)
|
171
187
|
end
|
172
188
|
|
173
189
|
# ENV Keys
|
174
|
-
# :
|
190
|
+
# :http_method - a symbolized request HTTP method (:get, :post)
|
175
191
|
# :body - the request body that will eventually be converted to a string.
|
176
192
|
# :url - URI instance for the current request.
|
177
193
|
# :status - HTTP response status code
|
@@ -187,25 +203,46 @@ module Faraday
|
|
187
203
|
# :password - Proxy server password
|
188
204
|
# :ssl - Hash of options for configuring SSL requests.
|
189
205
|
def build_env(connection, request)
|
190
|
-
|
191
|
-
|
192
|
-
request.options
|
193
|
-
|
206
|
+
exclusive_url = connection.build_exclusive_url(
|
207
|
+
request.path, request.params,
|
208
|
+
request.options.params_encoder
|
209
|
+
)
|
210
|
+
|
211
|
+
Env.new(request.http_method, request.body, exclusive_url,
|
212
|
+
request.options, request.headers, connection.ssl,
|
213
|
+
connection.parallel_manager)
|
194
214
|
end
|
195
215
|
|
196
216
|
private
|
197
217
|
|
218
|
+
LOCK_ERR = "can't modify middleware stack after making a request"
|
219
|
+
|
198
220
|
def raise_if_locked
|
199
|
-
raise StackLocked,
|
221
|
+
raise StackLocked, LOCK_ERR if locked?
|
200
222
|
end
|
201
223
|
|
202
|
-
def
|
224
|
+
def raise_if_adapter(klass)
|
225
|
+
return unless is_adapter?(klass)
|
226
|
+
|
227
|
+
raise 'Adapter should be set using the `adapter` method, not `use`'
|
228
|
+
end
|
229
|
+
|
230
|
+
def adapter_set?
|
231
|
+
!@adapter.nil?
|
232
|
+
end
|
233
|
+
|
234
|
+
def is_adapter?(klass) # rubocop:disable Naming/PredicateName
|
235
|
+
klass <= Faraday::Adapter
|
236
|
+
end
|
237
|
+
|
238
|
+
ruby2_keywords def use_symbol(mod, key, *args, &block)
|
203
239
|
use(mod.lookup_middleware(key), *args, &block)
|
204
240
|
end
|
205
241
|
|
206
242
|
def assert_index(index)
|
207
243
|
idx = index.is_a?(Integer) ? index : @handlers.index(index)
|
208
244
|
raise "No such handler: #{index.inspect}" unless idx
|
245
|
+
|
209
246
|
idx
|
210
247
|
end
|
211
248
|
end
|
@@ -1,42 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'base64'
|
4
|
+
|
1
5
|
module Faraday
|
2
|
-
class Request
|
3
|
-
|
6
|
+
class Request
|
7
|
+
# Request middleware for the Authorization HTTP header
|
8
|
+
class Authorization < Faraday::Middleware
|
9
|
+
unless defined?(::Faraday::Request::Authorization::KEY)
|
10
|
+
KEY = 'Authorization'
|
11
|
+
end
|
4
12
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
13
|
+
# @param type [String, Symbol]
|
14
|
+
# @param token [String, Symbol, Hash]
|
15
|
+
# @return [String] a header value
|
16
|
+
def self.header(type, token)
|
17
|
+
case token
|
18
|
+
when String, Symbol, Proc
|
19
|
+
token = token.call if token.is_a?(Proc)
|
20
|
+
"#{type} #{token}"
|
21
|
+
when Hash
|
22
|
+
build_hash(type.to_s, token)
|
23
|
+
else
|
24
|
+
raise ArgumentError,
|
25
|
+
"Can't build an Authorization #{type}" \
|
26
|
+
"header from #{token.inspect}"
|
27
|
+
end
|
14
28
|
end
|
15
|
-
end
|
16
29
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
values
|
30
|
+
# @param type [String]
|
31
|
+
# @param hash [Hash]
|
32
|
+
# @return [String] type followed by comma-separated key=value pairs
|
33
|
+
# @api private
|
34
|
+
def self.build_hash(type, hash)
|
35
|
+
comma = ', '
|
36
|
+
values = []
|
37
|
+
hash.each do |key, value|
|
38
|
+
value = value.call if value.is_a?(Proc)
|
39
|
+
values << "#{key}=#{value.to_s.inspect}"
|
40
|
+
end
|
41
|
+
"#{type} #{values * comma}"
|
24
42
|
end
|
25
|
-
"#{type} #{values * comma}"
|
26
|
-
end
|
27
43
|
|
28
|
-
|
29
|
-
@
|
30
|
-
|
31
|
-
|
44
|
+
# @param app [#call]
|
45
|
+
# @param type [String, Symbol] Type of Authorization
|
46
|
+
# @param param [String, Symbol, Hash, Proc] parameter to build the Authorization header.
|
47
|
+
# This value can be a proc, in which case it will be invoked on each request.
|
48
|
+
def initialize(app, type, param)
|
49
|
+
@type = type
|
50
|
+
@param = param
|
51
|
+
super(app)
|
52
|
+
end
|
32
53
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
54
|
+
# @param env [Faraday::Env]
|
55
|
+
def on_request(env)
|
56
|
+
return if env.request_headers[KEY]
|
57
|
+
|
58
|
+
env.request_headers[KEY] = self.class.header(@type, @param)
|
37
59
|
end
|
38
|
-
@app.call(env)
|
39
60
|
end
|
40
61
|
end
|
41
62
|
end
|
42
|
-
|
@@ -1,13 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'base64'
|
2
4
|
|
3
5
|
module Faraday
|
4
|
-
class Request
|
5
|
-
#
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
class Request
|
7
|
+
# Authorization middleware for Basic Authentication.
|
8
|
+
class BasicAuthentication < load_middleware(:authorization)
|
9
|
+
# @param login [String]
|
10
|
+
# @param pass [String]
|
11
|
+
#
|
12
|
+
# @return [String] a Basic Authentication header line
|
13
|
+
def self.header(login, pass)
|
14
|
+
value = Base64.encode64([login, pass].join(':'))
|
15
|
+
value.delete!("\n")
|
16
|
+
super(:Basic, value)
|
17
|
+
end
|
10
18
|
end
|
11
19
|
end
|
12
20
|
end
|
13
|
-
|
@@ -1,35 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Faraday
|
2
|
-
class Request
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
class Request
|
5
|
+
# Middleware for instrumenting Requests.
|
6
|
+
class Instrumentation < Faraday::Middleware
|
7
|
+
# Options class used in Request::Instrumentation class.
|
8
|
+
class Options < Faraday::Options.new(:name, :instrumenter)
|
9
|
+
# @return [String]
|
10
|
+
def name
|
11
|
+
self[:name] ||= 'request.faraday'
|
12
|
+
end
|
7
13
|
|
8
|
-
|
9
|
-
|
14
|
+
# @return [Class]
|
15
|
+
def instrumenter
|
16
|
+
self[:instrumenter] ||= ActiveSupport::Notifications
|
17
|
+
end
|
10
18
|
end
|
11
|
-
end
|
12
19
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
20
|
+
# Instruments requests using Active Support.
|
21
|
+
#
|
22
|
+
# Measures time spent only for synchronous requests.
|
23
|
+
#
|
24
|
+
# @example Using ActiveSupport::Notifications to measure time spent
|
25
|
+
# for Faraday requests.
|
26
|
+
# ActiveSupport::Notifications
|
27
|
+
# .subscribe('request.faraday') do |name, starts, ends, _, env|
|
28
|
+
# url = env[:url]
|
29
|
+
# http_method = env[:method].to_s.upcase
|
30
|
+
# duration = ends - starts
|
31
|
+
# $stderr.puts '[%s] %s %s (%.3f s)' %
|
32
|
+
# [url.host, http_method, url.request_uri, duration]
|
33
|
+
# end
|
34
|
+
# @param app [#call]
|
35
|
+
# @param options [nil, Hash] Options hash
|
36
|
+
# @option options [String] :name ('request.faraday')
|
37
|
+
# Name of the instrumenter
|
38
|
+
# @option options [Class] :instrumenter (ActiveSupport::Notifications)
|
39
|
+
# Active Support instrumenter class.
|
40
|
+
def initialize(app, options = nil)
|
41
|
+
super(app)
|
42
|
+
@name, @instrumenter = Options.from(options)
|
43
|
+
.values_at(:name, :instrumenter)
|
44
|
+
end
|
29
45
|
|
30
|
-
|
31
|
-
|
32
|
-
@
|
46
|
+
# @param env [Faraday::Env]
|
47
|
+
def call(env)
|
48
|
+
@instrumenter.instrument(@name, env) do
|
49
|
+
@app.call(env)
|
50
|
+
end
|
33
51
|
end
|
34
52
|
end
|
35
53
|
end
|
@@ -1,61 +1,104 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
self.mime_type = 'multipart/form-data'.freeze
|
6
|
-
DEFAULT_BOUNDARY = "-----------RubyMultipartPost".freeze unless defined? DEFAULT_BOUNDARY
|
3
|
+
require File.expand_path('url_encoded', __dir__)
|
4
|
+
require 'securerandom'
|
7
5
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
6
|
+
module Faraday
|
7
|
+
class Request
|
8
|
+
# Middleware for supporting multi-part requests.
|
9
|
+
class Multipart < UrlEncoded
|
10
|
+
self.mime_type = 'multipart/form-data'
|
11
|
+
unless defined?(::Faraday::Request::Multipart::DEFAULT_BOUNDARY_PREFIX)
|
12
|
+
DEFAULT_BOUNDARY_PREFIX = '-----------RubyMultipartPost'
|
13
13
|
end
|
14
|
-
@app.call env
|
15
|
-
end
|
16
14
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
type == self.class.mime_type
|
22
|
-
)
|
23
|
-
end
|
15
|
+
def initialize(app = nil, options = {})
|
16
|
+
super(app)
|
17
|
+
@options = options
|
18
|
+
end
|
24
19
|
|
25
|
-
|
26
|
-
#
|
27
|
-
|
28
|
-
|
29
|
-
|
20
|
+
# Checks for files in the payload, otherwise leaves everything untouched.
|
21
|
+
#
|
22
|
+
# @param env [Faraday::Env]
|
23
|
+
def call(env)
|
24
|
+
match_content_type(env) do |params|
|
25
|
+
env.request.boundary ||= unique_boundary
|
26
|
+
env.request_headers[CONTENT_TYPE] +=
|
27
|
+
"; boundary=#{env.request.boundary}"
|
28
|
+
env.body = create_multipart(env, params)
|
30
29
|
end
|
30
|
+
@app.call env
|
31
31
|
end
|
32
|
-
false
|
33
|
-
end
|
34
32
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
33
|
+
# @param env [Faraday::Env]
|
34
|
+
def process_request?(env)
|
35
|
+
type = request_type(env)
|
36
|
+
env.body.respond_to?(:each_key) && !env.body.empty? && (
|
37
|
+
(type.empty? && has_multipart?(env.body)) ||
|
38
|
+
(type == self.class.mime_type)
|
39
|
+
)
|
39
40
|
end
|
40
|
-
parts << Faraday::Parts::EpiloguePart.new(boundary)
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
42
|
+
# Returns true if obj is an enumerable with values that are multipart.
|
43
|
+
#
|
44
|
+
# @param obj [Object]
|
45
|
+
# @return [Boolean]
|
46
|
+
def has_multipart?(obj) # rubocop:disable Naming/PredicateName
|
47
|
+
if obj.respond_to?(:each)
|
48
|
+
(obj.respond_to?(:values) ? obj.values : obj).each do |val|
|
49
|
+
return true if val.respond_to?(:content_type) || has_multipart?(val)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
false
|
53
|
+
end
|
46
54
|
|
47
|
-
|
48
|
-
params
|
49
|
-
|
55
|
+
# @param env [Faraday::Env]
|
56
|
+
# @param params [Hash]
|
57
|
+
def create_multipart(env, params)
|
58
|
+
boundary = env.request.boundary
|
59
|
+
parts = process_params(params) do |key, value|
|
60
|
+
part(boundary, key, value)
|
61
|
+
end
|
62
|
+
parts << Faraday::Parts::EpiloguePart.new(boundary)
|
63
|
+
|
64
|
+
body = Faraday::CompositeReadIO.new(parts)
|
65
|
+
env.request_headers[Faraday::Env::ContentLength] = body.length.to_s
|
66
|
+
body
|
67
|
+
end
|
50
68
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
process_params(values, key, all, &block)
|
55
|
-
when Hash
|
56
|
-
process_params(value, key, all, &block)
|
69
|
+
def part(boundary, key, value)
|
70
|
+
if value.respond_to?(:to_part)
|
71
|
+
value.to_part(boundary, key)
|
57
72
|
else
|
58
|
-
|
73
|
+
Faraday::Parts::Part.new(boundary, key, value)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# @return [String]
|
78
|
+
def unique_boundary
|
79
|
+
"#{DEFAULT_BOUNDARY_PREFIX}-#{SecureRandom.hex}"
|
80
|
+
end
|
81
|
+
|
82
|
+
# @param params [Hash]
|
83
|
+
# @param prefix [String]
|
84
|
+
# @param pieces [Array]
|
85
|
+
def process_params(params, prefix = nil, pieces = nil, &block)
|
86
|
+
params.inject(pieces || []) do |all, (key, value)|
|
87
|
+
if prefix
|
88
|
+
key = @options[:flat_encode] ? prefix.to_s : "#{prefix}[#{key}]"
|
89
|
+
end
|
90
|
+
|
91
|
+
case value
|
92
|
+
when Array
|
93
|
+
values = value.inject([]) { |a, v| a << [nil, v] }
|
94
|
+
process_params(values, key, all, &block)
|
95
|
+
when Hash
|
96
|
+
process_params(value, key, all, &block)
|
97
|
+
else
|
98
|
+
# rubocop:disable Performance/RedundantBlockCall
|
99
|
+
all << block.call(key, value)
|
100
|
+
# rubocop:enable Performance/RedundantBlockCall
|
101
|
+
end
|
59
102
|
end
|
60
103
|
end
|
61
104
|
end
|