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/adapter.rb
CHANGED
@@ -1,54 +1,43 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
module Faraday
|
4
|
-
#
|
2
|
+
# Public: This is a base class for all Faraday adapters. Adapters are
|
5
3
|
# responsible for fulfilling a Faraday request.
|
6
|
-
class Adapter
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
em_http: [:EMHttp, 'em_http'],
|
23
|
-
excon: [:Excon, 'excon'],
|
24
|
-
rack: [:Rack, 'rack'],
|
25
|
-
httpclient: [:HTTPClient, 'httpclient']
|
26
|
-
|
27
|
-
# This module marks an Adapter as supporting parallel requests.
|
4
|
+
class Adapter < Middleware
|
5
|
+
CONTENT_LENGTH = 'Content-Length'.freeze
|
6
|
+
|
7
|
+
register_middleware File.expand_path('../adapter', __FILE__),
|
8
|
+
:test => [:Test, 'test'],
|
9
|
+
:net_http => [:NetHttp, 'net_http'],
|
10
|
+
:net_http_persistent => [:NetHttpPersistent, 'net_http_persistent'],
|
11
|
+
:typhoeus => [:Typhoeus, 'typhoeus'],
|
12
|
+
:patron => [:Patron, 'patron'],
|
13
|
+
:em_synchrony => [:EMSynchrony, 'em_synchrony'],
|
14
|
+
:em_http => [:EMHttp, 'em_http'],
|
15
|
+
:excon => [:Excon, 'excon'],
|
16
|
+
:rack => [:Rack, 'rack'],
|
17
|
+
:httpclient => [:HTTPClient, 'httpclient']
|
18
|
+
|
19
|
+
# Public: This module marks an Adapter as supporting parallel requests.
|
28
20
|
module Parallelism
|
29
21
|
attr_writer :supports_parallel
|
30
|
-
def supports_parallel?
|
31
|
-
@supports_parallel
|
32
|
-
end
|
22
|
+
def supports_parallel?() @supports_parallel end
|
33
23
|
|
34
24
|
def inherited(subclass)
|
35
25
|
super
|
36
|
-
subclass.supports_parallel = supports_parallel?
|
26
|
+
subclass.supports_parallel = self.supports_parallel?
|
37
27
|
end
|
38
28
|
end
|
39
29
|
|
40
30
|
extend Parallelism
|
41
31
|
self.supports_parallel = false
|
42
32
|
|
43
|
-
def initialize(
|
44
|
-
|
33
|
+
def initialize(app = nil, opts = {}, &block)
|
34
|
+
super(app)
|
45
35
|
@connection_options = opts
|
46
36
|
@config_block = block
|
47
37
|
end
|
48
38
|
|
49
39
|
def call(env)
|
50
40
|
env.clear_body if env.needs_body?
|
51
|
-
env.response = Response.new
|
52
41
|
end
|
53
42
|
|
54
43
|
private
|
@@ -56,14 +45,11 @@ module Faraday
|
|
56
45
|
def save_response(env, status, body, headers = nil, reason_phrase = nil)
|
57
46
|
env.status = status
|
58
47
|
env.body = body
|
59
|
-
env.reason_phrase = reason_phrase
|
48
|
+
env.reason_phrase = reason_phrase && reason_phrase.to_s.strip
|
60
49
|
env.response_headers = Utils::Headers.new.tap do |response_headers|
|
61
50
|
response_headers.update headers unless headers.nil?
|
62
51
|
yield(response_headers) if block_given?
|
63
52
|
end
|
64
|
-
|
65
|
-
env.response.finish(env) unless env.parallel?
|
66
|
-
env.response
|
67
53
|
end
|
68
54
|
end
|
69
55
|
end
|
@@ -1,15 +1,10 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
module Faraday
|
4
2
|
class Adapter
|
5
|
-
# EventMachine adapter
|
6
|
-
#
|
3
|
+
# EventMachine adapter is useful for either asynchronous requests
|
4
|
+
# when in EM reactor loop or for making parallel requests in
|
7
5
|
# synchronous code.
|
8
6
|
class EMHttp < Faraday::Adapter
|
9
|
-
# Options is a module containing helpers to convert the Faraday env object
|
10
|
-
# into options hashes for EMHTTP method calls.
|
11
7
|
module Options
|
12
|
-
# @return [Hash]
|
13
8
|
def connection_config(env)
|
14
9
|
options = {}
|
15
10
|
configure_proxy(options, env)
|
@@ -21,10 +16,10 @@ module Faraday
|
|
21
16
|
|
22
17
|
def request_config(env)
|
23
18
|
options = {
|
24
|
-
body
|
25
|
-
head
|
26
|
-
# keepalive
|
27
|
-
# file
|
19
|
+
:body => read_body(env),
|
20
|
+
:head => env[:request_headers],
|
21
|
+
# :keepalive => true,
|
22
|
+
# :file => 'path/to/file', # stream data off disk
|
28
23
|
}
|
29
24
|
configure_compression(options, env)
|
30
25
|
options
|
@@ -35,53 +30,44 @@ module Faraday
|
|
35
30
|
body.respond_to?(:read) ? body.read : body
|
36
31
|
end
|
37
32
|
|
38
|
-
# Reads out proxy settings from env into options
|
39
33
|
def configure_proxy(options, env)
|
40
|
-
proxy = request_options(env)[:proxy]
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
}
|
34
|
+
if proxy = request_options(env)[:proxy]
|
35
|
+
options[:proxy] = {
|
36
|
+
:host => proxy[:uri].host,
|
37
|
+
:port => proxy[:uri].port,
|
38
|
+
:authorization => [proxy[:user], proxy[:password]]
|
39
|
+
}
|
40
|
+
end
|
48
41
|
end
|
49
42
|
|
50
|
-
# Reads out host and port settings from env into options
|
51
43
|
def configure_socket(options, env)
|
52
|
-
bind = request_options(env)[:bind]
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
}
|
44
|
+
if bind = request_options(env)[:bind]
|
45
|
+
options[:bind] = {
|
46
|
+
:host => bind[:host],
|
47
|
+
:port => bind[:port]
|
48
|
+
}
|
49
|
+
end
|
59
50
|
end
|
60
51
|
|
61
|
-
# Reads out SSL certificate settings from env into options
|
62
52
|
def configure_ssl(options, env)
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
53
|
+
if env[:url].scheme == 'https' && env[:ssl]
|
54
|
+
options[:ssl] = {
|
55
|
+
:cert_chain_file => env[:ssl][:ca_file],
|
56
|
+
:verify_peer => env[:ssl].fetch(:verify, true)
|
57
|
+
}
|
58
|
+
end
|
69
59
|
end
|
70
60
|
|
71
|
-
# Reads out timeout settings from env into options
|
72
61
|
def configure_timeout(options, env)
|
73
|
-
timeout, open_timeout = request_options(env)
|
74
|
-
.values_at(:timeout, :open_timeout)
|
62
|
+
timeout, open_timeout = request_options(env).values_at(:timeout, :open_timeout)
|
75
63
|
options[:connect_timeout] = options[:inactivity_timeout] = timeout
|
76
64
|
options[:connect_timeout] = open_timeout if open_timeout
|
77
65
|
end
|
78
66
|
|
79
|
-
# Reads out compression header settings from env into options
|
80
67
|
def configure_compression(options, env)
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
options[:head]['accept-encoding'] = 'gzip, compressed'
|
68
|
+
if env[:method] == :get and not options[:head].key? 'accept-encoding'
|
69
|
+
options[:head]['accept-encoding'] = 'gzip, compressed'
|
70
|
+
end
|
85
71
|
end
|
86
72
|
|
87
73
|
def request_options(env)
|
@@ -95,8 +81,7 @@ module Faraday
|
|
95
81
|
|
96
82
|
self.supports_parallel = true
|
97
83
|
|
98
|
-
|
99
|
-
def self.setup_parallel_manager(_options = nil)
|
84
|
+
def self.setup_parallel_manager(options = nil)
|
100
85
|
Manager.new
|
101
86
|
end
|
102
87
|
|
@@ -109,113 +94,95 @@ module Faraday
|
|
109
94
|
def perform_request(env)
|
110
95
|
if parallel?(env)
|
111
96
|
manager = env[:parallel_manager]
|
112
|
-
manager.add
|
113
|
-
perform_single_request(env)
|
114
|
-
|
115
|
-
|
116
|
-
elsif EventMachine.reactor_running?
|
117
|
-
# EM is running: instruct upstream that this is an async request
|
118
|
-
env[:parallel_manager] = true
|
119
|
-
perform_single_request(env)
|
120
|
-
.callback { env[:response].finish(env) }
|
121
|
-
.errback do
|
122
|
-
# TODO: no way to communicate the error in async mode
|
123
|
-
raise NotImplementedError
|
124
|
-
end
|
97
|
+
manager.add {
|
98
|
+
perform_single_request(env).
|
99
|
+
callback { env[:response].finish(env) }
|
100
|
+
}
|
125
101
|
else
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
.
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
102
|
+
unless EventMachine.reactor_running?
|
103
|
+
error = nil
|
104
|
+
# start EM, block until request is completed
|
105
|
+
EventMachine.run do
|
106
|
+
perform_single_request(env).
|
107
|
+
callback { EventMachine.stop }.
|
108
|
+
errback { |client|
|
109
|
+
error = error_message(client)
|
110
|
+
EventMachine.stop
|
111
|
+
}
|
112
|
+
end
|
113
|
+
raise_error(error) if error
|
114
|
+
else
|
115
|
+
# EM is running: instruct upstream that this is an async request
|
116
|
+
env[:parallel_manager] = true
|
117
|
+
perform_single_request(env).
|
118
|
+
callback { env[:response].finish(env) }.
|
119
|
+
errback {
|
120
|
+
# TODO: no way to communicate the error in async mode
|
121
|
+
raise NotImplementedError
|
122
|
+
}
|
135
123
|
end
|
136
|
-
raise_error(error) if error
|
137
124
|
end
|
138
|
-
rescue EventMachine::Connectify::CONNECTError =>
|
139
|
-
if
|
140
|
-
raise
|
141
|
-
|
125
|
+
rescue EventMachine::Connectify::CONNECTError => err
|
126
|
+
if err.message.include?("Proxy Authentication Required")
|
127
|
+
raise Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
|
128
|
+
else
|
129
|
+
raise Error::ConnectionFailed, err
|
142
130
|
end
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
raise
|
131
|
+
rescue => err
|
132
|
+
if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err
|
133
|
+
raise Faraday::SSLError, err
|
134
|
+
else
|
135
|
+
raise
|
148
136
|
end
|
149
|
-
|
150
|
-
raise
|
151
137
|
end
|
152
138
|
|
153
139
|
# TODO: reuse the connection to support pipelining
|
154
140
|
def perform_single_request(env)
|
155
141
|
req = create_request(env)
|
156
|
-
req
|
157
|
-
req.callback do |client|
|
158
|
-
if env[:request].stream_response?
|
159
|
-
warn "Streaming downloads for #{self.class.name} " \
|
160
|
-
'are not yet implemented.'
|
161
|
-
env[:request].on_data.call(
|
162
|
-
client.response,
|
163
|
-
client.response.bytesize
|
164
|
-
)
|
165
|
-
end
|
142
|
+
req.setup_request(env[:method], request_config(env)).callback { |client|
|
166
143
|
status = client.response_header.status
|
167
144
|
reason = client.response_header.http_reason
|
168
|
-
save_response(env, status, client.response, nil, reason) do |
|
145
|
+
save_response(env, status, client.response, nil, reason) do |resp_headers|
|
169
146
|
client.response_header.each do |name, value|
|
170
|
-
|
147
|
+
resp_headers[name.to_sym] = value
|
171
148
|
end
|
172
149
|
end
|
173
|
-
|
150
|
+
}
|
174
151
|
end
|
175
152
|
|
176
153
|
def create_request(env)
|
177
|
-
EventMachine::HttpRequest.new(
|
178
|
-
env[:url], connection_config(env).merge(@connection_options)
|
179
|
-
)
|
154
|
+
EventMachine::HttpRequest.new(env[:url], connection_config(env).merge(@connection_options))
|
180
155
|
end
|
181
156
|
|
182
157
|
def error_message(client)
|
183
|
-
client.error
|
158
|
+
client.error or "request failed"
|
184
159
|
end
|
185
160
|
|
186
161
|
def raise_error(msg)
|
187
|
-
|
188
|
-
if
|
189
|
-
|
190
|
-
msg =
|
162
|
+
errklass = Faraday::Error::ClientError
|
163
|
+
if msg == Errno::ETIMEDOUT
|
164
|
+
errklass = Faraday::Error::TimeoutError
|
165
|
+
msg = "request timed out"
|
191
166
|
elsif msg == Errno::ECONNREFUSED
|
192
|
-
|
193
|
-
msg =
|
194
|
-
elsif msg ==
|
195
|
-
|
167
|
+
errklass = Faraday::Error::ConnectionFailed
|
168
|
+
msg = "connection refused"
|
169
|
+
elsif msg == "connection closed by server"
|
170
|
+
errklass = Faraday::Error::ConnectionFailed
|
196
171
|
end
|
197
|
-
raise
|
172
|
+
raise errklass, msg
|
198
173
|
end
|
199
174
|
|
200
|
-
def timeout_message?(msg)
|
201
|
-
msg == Errno::ETIMEDOUT ||
|
202
|
-
(msg.is_a?(String) && msg.include?('timeout error'))
|
203
|
-
end
|
204
|
-
|
205
|
-
# @return [Boolean]
|
206
175
|
def parallel?(env)
|
207
176
|
!!env[:parallel_manager]
|
208
177
|
end
|
209
178
|
|
210
|
-
#
|
179
|
+
# The parallel manager is designed to start an EventMachine loop
|
211
180
|
# and block until all registered requests have been completed.
|
212
181
|
class Manager
|
213
|
-
# @see reset
|
214
182
|
def initialize
|
215
183
|
reset
|
216
184
|
end
|
217
185
|
|
218
|
-
# Re-initializes instance variables
|
219
186
|
def reset
|
220
187
|
@registered_procs = []
|
221
188
|
@num_registered = 0
|
@@ -224,30 +191,27 @@ module Faraday
|
|
224
191
|
@running = false
|
225
192
|
end
|
226
193
|
|
227
|
-
|
228
|
-
def running?
|
229
|
-
@running
|
230
|
-
end
|
194
|
+
def running?() @running end
|
231
195
|
|
232
|
-
def add
|
196
|
+
def add
|
233
197
|
if running?
|
234
198
|
perform_request { yield }
|
235
199
|
else
|
236
|
-
@registered_procs <<
|
200
|
+
@registered_procs << Proc.new
|
237
201
|
end
|
238
202
|
@num_registered += 1
|
239
203
|
end
|
240
204
|
|
241
205
|
def run
|
242
|
-
if @num_registered
|
206
|
+
if @num_registered > 0
|
243
207
|
@running = true
|
244
208
|
EventMachine.run do
|
245
209
|
@registered_procs.each do |proc|
|
246
210
|
perform_request(&proc)
|
247
211
|
end
|
248
212
|
end
|
249
|
-
|
250
|
-
raise Faraday::ClientError, @errors.first ||
|
213
|
+
if @errors.size > 0
|
214
|
+
raise Faraday::Error::ClientError, @errors.first || "connection failed"
|
251
215
|
end
|
252
216
|
end
|
253
217
|
ensure
|
@@ -256,31 +220,24 @@ module Faraday
|
|
256
220
|
|
257
221
|
def perform_request
|
258
222
|
client = yield
|
259
|
-
client.callback
|
260
|
-
|
261
|
-
check_finished
|
262
|
-
end
|
263
|
-
client.errback do
|
264
|
-
@errors << client.error
|
265
|
-
check_finished
|
266
|
-
end
|
223
|
+
client.callback { @num_succeeded += 1; check_finished }
|
224
|
+
client.errback { @errors << client.error; check_finished }
|
267
225
|
end
|
268
226
|
|
269
227
|
def check_finished
|
270
|
-
|
228
|
+
if @num_succeeded + @errors.size == @num_registered
|
229
|
+
EventMachine.stop
|
230
|
+
end
|
271
231
|
end
|
272
232
|
end
|
273
233
|
end
|
274
234
|
end
|
275
235
|
end
|
276
236
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
require 'faraday/adapter/em_http_ssl_patch'
|
285
|
-
end
|
286
|
-
end
|
237
|
+
begin
|
238
|
+
require 'openssl'
|
239
|
+
rescue LoadError
|
240
|
+
warn "Warning: no such file to load -- openssl. Make sure it is installed if you want HTTPS support"
|
241
|
+
else
|
242
|
+
require 'faraday/adapter/em_http_ssl_patch'
|
243
|
+
end if Faraday::Adapter::EMHttp.loaded?
|