faraday 0.15.4 → 0.16.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 +18 -344
- data/lib/faraday.rb +93 -175
- data/lib/faraday/adapter.rb +36 -22
- data/lib/faraday/adapter/em_http.rb +142 -99
- data/lib/faraday/adapter/em_http_ssl_patch.rb +23 -17
- data/lib/faraday/adapter/em_synchrony.rb +104 -60
- data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +18 -15
- data/lib/faraday/adapter/excon.rb +100 -55
- data/lib/faraday/adapter/httpclient.rb +61 -39
- data/lib/faraday/adapter/net_http.rb +104 -51
- data/lib/faraday/adapter/net_http_persistent.rb +48 -27
- data/lib/faraday/adapter/patron.rb +54 -35
- data/lib/faraday/adapter/rack.rb +28 -12
- data/lib/faraday/adapter/test.rb +86 -53
- data/lib/faraday/adapter/typhoeus.rb +4 -1
- data/lib/faraday/adapter_registry.rb +28 -0
- data/lib/faraday/autoload.rb +47 -36
- data/lib/faraday/connection.rb +321 -179
- data/lib/faraday/dependency_loader.rb +37 -0
- data/lib/faraday/encoders/flat_params_encoder.rb +94 -0
- data/lib/faraday/encoders/nested_params_encoder.rb +171 -0
- data/lib/faraday/error.rb +67 -33
- data/lib/faraday/file_part.rb +128 -0
- data/lib/faraday/logging/formatter.rb +92 -0
- data/lib/faraday/middleware.rb +4 -28
- data/lib/faraday/middleware_registry.rb +129 -0
- data/lib/faraday/options.rb +35 -186
- data/lib/faraday/options/connection_options.rb +22 -0
- data/lib/faraday/options/env.rb +181 -0
- data/lib/faraday/options/proxy_options.rb +28 -0
- data/lib/faraday/options/request_options.rb +21 -0
- data/lib/faraday/options/ssl_options.rb +59 -0
- data/lib/faraday/param_part.rb +53 -0
- data/lib/faraday/parameters.rb +4 -197
- data/lib/faraday/rack_builder.rb +67 -56
- data/lib/faraday/request.rb +68 -36
- data/lib/faraday/request/authorization.rb +42 -30
- data/lib/faraday/request/basic_authentication.rb +14 -7
- data/lib/faraday/request/instrumentation.rb +45 -27
- data/lib/faraday/request/multipart.rb +79 -48
- data/lib/faraday/request/retry.rb +198 -169
- data/lib/faraday/request/token_authentication.rb +15 -10
- data/lib/faraday/request/url_encoded.rb +41 -23
- data/lib/faraday/response.rb +23 -16
- data/lib/faraday/response/logger.rb +22 -69
- data/lib/faraday/response/raise_error.rb +36 -14
- data/lib/faraday/utils.rb +28 -245
- data/lib/faraday/utils/headers.rb +139 -0
- data/lib/faraday/utils/params_hash.rb +61 -0
- data/spec/external_adapters/faraday_specs_setup.rb +14 -0
- metadata +21 -5
- data/lib/faraday/upload_io.rb +0 -67
@@ -1,5 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Faraday
|
2
4
|
class Adapter
|
5
|
+
# Patron adapter.
|
3
6
|
class Patron < Faraday::Adapter
|
4
7
|
dependency 'patron'
|
5
8
|
|
@@ -9,46 +12,60 @@ module Faraday
|
|
9
12
|
env[:body] = env[:body].read if env[:body].respond_to? :read
|
10
13
|
|
11
14
|
session = ::Patron::Session.new
|
12
|
-
@config_block
|
13
|
-
|
15
|
+
@config_block&.call(session)
|
16
|
+
if (env[:url].scheme == 'https') && env[:ssl]
|
17
|
+
configure_ssl(session, env[:ssl])
|
18
|
+
end
|
14
19
|
|
15
|
-
if req = env[:request]
|
16
|
-
|
17
|
-
|
20
|
+
if (req = env[:request])
|
21
|
+
if req[:timeout]
|
22
|
+
session.timeout = session.connect_timeout = req[:timeout]
|
23
|
+
end
|
24
|
+
session.connect_timeout = req[:open_timeout] if req[:open_timeout]
|
18
25
|
|
19
|
-
if proxy = req[:proxy]
|
26
|
+
if (proxy = req[:proxy])
|
20
27
|
proxy_uri = proxy[:uri].dup
|
21
|
-
proxy_uri.user = proxy[:user] &&
|
22
|
-
|
28
|
+
proxy_uri.user = proxy[:user] &&
|
29
|
+
Utils.escape(proxy[:user]).gsub('+', '%20')
|
30
|
+
proxy_uri.password = proxy[:password] &&
|
31
|
+
Utils.escape(proxy[:password]).gsub('+', '%20')
|
23
32
|
session.proxy = proxy_uri.to_s
|
24
33
|
end
|
25
34
|
end
|
26
35
|
|
27
36
|
response = begin
|
28
37
|
data = env[:body] ? env[:body].to_s : nil
|
29
|
-
session.request(env[:method], env[:url].to_s,
|
30
|
-
|
31
|
-
|
38
|
+
session.request(env[:method], env[:url].to_s,
|
39
|
+
env[:request_headers], data: data)
|
40
|
+
rescue Errno::ECONNREFUSED, ::Patron::ConnectionFailed
|
41
|
+
raise Faraday::ConnectionFailed, $ERROR_INFO
|
32
42
|
end
|
33
43
|
|
44
|
+
if (req = env[:request]).stream_response?
|
45
|
+
warn "Streaming downloads for #{self.class.name} " \
|
46
|
+
'are not yet implemented.'
|
47
|
+
req.on_data.call(response.body, response.body.bytesize)
|
48
|
+
end
|
34
49
|
# Remove the "HTTP/1.1 200", leaving just the reason phrase
|
35
50
|
reason_phrase = response.status_line.gsub(/^.* \d{3} /, '')
|
36
51
|
|
37
|
-
save_response(env, response.status, response.body,
|
52
|
+
save_response(env, response.status, response.body,
|
53
|
+
response.headers, reason_phrase)
|
38
54
|
|
39
55
|
@app.call env
|
40
|
-
rescue ::Patron::TimeoutError =>
|
41
|
-
if connection_timed_out_message?(
|
42
|
-
raise Faraday::
|
43
|
-
else
|
44
|
-
raise Faraday::Error::TimeoutError, err
|
56
|
+
rescue ::Patron::TimeoutError => e
|
57
|
+
if connection_timed_out_message?(e.message)
|
58
|
+
raise Faraday::ConnectionFailed, e
|
45
59
|
end
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
raise
|
60
|
+
|
61
|
+
raise Faraday::TimeoutError, e
|
62
|
+
rescue ::Patron::Error => e
|
63
|
+
if e.message.include?('code 407')
|
64
|
+
raise Faraday::ConnectionFailed,
|
65
|
+
%(407 "Proxy Authentication Required ")
|
51
66
|
end
|
67
|
+
|
68
|
+
raise Faraday::ConnectionFailed, e
|
52
69
|
end
|
53
70
|
|
54
71
|
if loaded? && defined?(::Patron::Request::VALID_ACTIONS)
|
@@ -60,8 +77,8 @@ module Faraday
|
|
60
77
|
actions << :options unless actions.include? :options
|
61
78
|
else
|
62
79
|
# Patron 0.4.20 and up
|
63
|
-
actions <<
|
64
|
-
actions <<
|
80
|
+
actions << 'PATCH' unless actions.include? 'PATCH'
|
81
|
+
actions << 'OPTIONS' unless actions.include? 'OPTIONS'
|
65
82
|
end
|
66
83
|
end
|
67
84
|
end
|
@@ -76,20 +93,22 @@ module Faraday
|
|
76
93
|
|
77
94
|
private
|
78
95
|
|
79
|
-
CURL_TIMEOUT_MESSAGES = [
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
96
|
+
CURL_TIMEOUT_MESSAGES = [
|
97
|
+
'Connection time-out',
|
98
|
+
'Connection timed out',
|
99
|
+
'Timed out before name resolve',
|
100
|
+
'server connect has timed out',
|
101
|
+
'Resolving timed out',
|
102
|
+
'name lookup timed out',
|
103
|
+
'timed out before SSL',
|
104
|
+
'connect() timed out'
|
105
|
+
].freeze
|
88
106
|
|
89
107
|
def connection_timed_out_message?(message)
|
90
|
-
CURL_TIMEOUT_MESSAGES.any?
|
108
|
+
CURL_TIMEOUT_MESSAGES.any? do |curl_message|
|
109
|
+
message.include?(curl_message)
|
110
|
+
end
|
91
111
|
end
|
92
|
-
|
93
112
|
end
|
94
113
|
end
|
95
114
|
end
|
data/lib/faraday/adapter/rack.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Faraday
|
2
4
|
class Adapter
|
3
5
|
# Sends requests to a Rack app.
|
4
6
|
#
|
5
|
-
#
|
7
|
+
# @example
|
6
8
|
#
|
7
9
|
# class MyRackApp
|
8
10
|
# def call(env)
|
@@ -17,7 +19,7 @@ module Faraday
|
|
17
19
|
dependency 'rack/test'
|
18
20
|
|
19
21
|
# not prefixed with "HTTP_"
|
20
|
-
SPECIAL_HEADERS = %w[
|
22
|
+
SPECIAL_HEADERS = %w[CONTENT_LENGTH CONTENT_TYPE].freeze
|
21
23
|
|
22
24
|
def initialize(faraday_app, rack_app)
|
23
25
|
super(faraday_app)
|
@@ -27,32 +29,46 @@ module Faraday
|
|
27
29
|
|
28
30
|
def call(env)
|
29
31
|
super
|
30
|
-
rack_env =
|
31
|
-
:method => env[:method],
|
32
|
-
:input => env[:body].respond_to?(:read) ? env[:body].read : env[:body],
|
33
|
-
'rack.url_scheme' => env[:url].scheme
|
34
|
-
}
|
32
|
+
rack_env = build_rack_env(env)
|
35
33
|
|
36
|
-
env[:request_headers]
|
34
|
+
env[:request_headers]&.each do |name, value|
|
37
35
|
name = name.upcase.tr('-', '_')
|
38
36
|
name = "HTTP_#{name}" unless SPECIAL_HEADERS.include? name
|
39
37
|
rack_env[name] = value
|
40
|
-
end
|
38
|
+
end
|
41
39
|
|
42
40
|
timeout = env[:request][:timeout] || env[:request][:open_timeout]
|
43
41
|
response = if timeout
|
44
|
-
|
45
|
-
|
46
|
-
|
42
|
+
Timer.timeout(timeout, Faraday::TimeoutError) do
|
43
|
+
execute_request(env, rack_env)
|
44
|
+
end
|
45
|
+
else
|
46
|
+
execute_request(env, rack_env)
|
47
|
+
end
|
48
|
+
|
49
|
+
if (req = env[:request]).stream_response?
|
50
|
+
warn "Streaming downloads for #{self.class.name} " \
|
51
|
+
'are not yet implemented.'
|
52
|
+
req.on_data.call(response.body, response.body.bytesize)
|
47
53
|
end
|
48
54
|
|
49
55
|
save_response(env, response.status, response.body, response.headers)
|
50
56
|
@app.call env
|
51
57
|
end
|
52
58
|
|
59
|
+
private
|
60
|
+
|
53
61
|
def execute_request(env, rack_env)
|
54
62
|
@session.request(env[:url].to_s, rack_env)
|
55
63
|
end
|
64
|
+
|
65
|
+
def build_rack_env(env)
|
66
|
+
{
|
67
|
+
method: env[:method],
|
68
|
+
input: env[:body].respond_to?(:read) ? env[:body].read : env[:body],
|
69
|
+
'rack.url_scheme' => env[:url].scheme
|
70
|
+
}
|
71
|
+
end
|
56
72
|
end
|
57
73
|
end
|
58
74
|
end
|
data/lib/faraday/adapter/test.rb
CHANGED
@@ -1,51 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Faraday
|
2
4
|
class Adapter
|
3
|
-
#
|
4
|
-
#
|
5
|
+
# @example
|
5
6
|
# test = Faraday::Connection.new do
|
6
7
|
# use Faraday::Adapter::Test do |stub|
|
7
|
-
# #
|
8
|
+
# # Define matcher to match the request
|
8
9
|
# stub.get '/resource.json' do
|
9
10
|
# # return static content
|
10
11
|
# [200, {'Content-Type' => 'application/json'}, 'hi world']
|
11
12
|
# end
|
12
|
-
#
|
13
|
+
#
|
13
14
|
# # response with content generated based on request
|
14
15
|
# stub.get '/showget' do |env|
|
15
16
|
# [200, {'Content-Type' => 'text/plain'}, env[:method].to_s]
|
16
17
|
# end
|
17
|
-
#
|
18
|
-
# # regular expression can be used as matching filter
|
18
|
+
#
|
19
|
+
# # A regular expression can be used as matching filter
|
19
20
|
# stub.get /\A\/items\/(\d+)\z/ do |env, meta|
|
20
|
-
# # in case regular expression is used an instance of MatchData
|
21
|
-
#
|
21
|
+
# # in case regular expression is used, an instance of MatchData
|
22
|
+
# # can be received
|
23
|
+
# [200,
|
24
|
+
# {'Content-Type' => 'text/plain'},
|
25
|
+
# "showing item: #{meta[:match_data][1]}"
|
26
|
+
# ]
|
22
27
|
# end
|
23
28
|
# end
|
24
29
|
# end
|
25
|
-
#
|
30
|
+
#
|
26
31
|
# resp = test.get '/resource.json'
|
27
32
|
# resp.body # => 'hi world'
|
28
|
-
#
|
33
|
+
#
|
29
34
|
# resp = test.get '/showget'
|
30
35
|
# resp.body # => 'get'
|
31
|
-
#
|
36
|
+
#
|
32
37
|
# resp = test.get '/items/1'
|
33
38
|
# resp.body # => 'showing item: 1'
|
34
|
-
#
|
39
|
+
#
|
35
40
|
# resp = test.get '/items/2'
|
36
41
|
# resp.body # => 'showing item: 2'
|
37
|
-
#
|
38
|
-
|
39
42
|
class Test < Faraday::Adapter
|
40
43
|
attr_accessor :stubs
|
41
44
|
|
45
|
+
# A stack of Stubs
|
42
46
|
class Stubs
|
43
47
|
class NotFound < StandardError
|
44
48
|
end
|
45
49
|
|
46
50
|
def initialize
|
47
|
-
# {:
|
48
|
-
@stack
|
51
|
+
# { get: [Stub, Stub] }
|
52
|
+
@stack = {}
|
53
|
+
@consumed = {}
|
49
54
|
yield(self) if block_given?
|
50
55
|
end
|
51
56
|
|
@@ -54,7 +59,8 @@ module Faraday
|
|
54
59
|
end
|
55
60
|
|
56
61
|
def match(request_method, host, path, headers, body)
|
57
|
-
return false
|
62
|
+
return false unless @stack.key?(request_method)
|
63
|
+
|
58
64
|
stack = @stack[request_method]
|
59
65
|
consumed = (@consumed[request_method] ||= [])
|
60
66
|
|
@@ -74,15 +80,15 @@ module Faraday
|
|
74
80
|
new_stub(:head, path, headers, &block)
|
75
81
|
end
|
76
82
|
|
77
|
-
def post(path, body=nil, headers = {}, &block)
|
83
|
+
def post(path, body = nil, headers = {}, &block)
|
78
84
|
new_stub(:post, path, headers, body, &block)
|
79
85
|
end
|
80
86
|
|
81
|
-
def put(path, body=nil, headers = {}, &block)
|
87
|
+
def put(path, body = nil, headers = {}, &block)
|
82
88
|
new_stub(:put, path, headers, body, &block)
|
83
89
|
end
|
84
90
|
|
85
|
-
def patch(path, body=nil, headers = {}, &block)
|
91
|
+
def patch(path, body = nil, headers = {}, &block)
|
86
92
|
new_stub(:patch, path, headers, body, &block)
|
87
93
|
end
|
88
94
|
|
@@ -98,26 +104,32 @@ module Faraday
|
|
98
104
|
def verify_stubbed_calls
|
99
105
|
failed_stubs = []
|
100
106
|
@stack.each do |method, stubs|
|
101
|
-
|
102
|
-
|
107
|
+
next if stubs.empty?
|
108
|
+
|
109
|
+
failed_stubs.concat(
|
110
|
+
stubs.map do |stub|
|
103
111
|
"Expected #{method} #{stub}."
|
104
|
-
|
105
|
-
|
112
|
+
end
|
113
|
+
)
|
106
114
|
end
|
107
|
-
raise failed_stubs.join(
|
115
|
+
raise failed_stubs.join(' ') unless failed_stubs.empty?
|
108
116
|
end
|
109
117
|
|
110
118
|
protected
|
111
119
|
|
112
|
-
def new_stub(request_method, path, headers = {}, body=nil, &block)
|
120
|
+
def new_stub(request_method, path, headers = {}, body = nil, &block)
|
113
121
|
normalized_path, host =
|
114
122
|
if path.is_a?(Regexp)
|
115
123
|
path
|
116
124
|
else
|
117
|
-
[
|
125
|
+
[
|
126
|
+
Faraday::Utils.normalize_path(path),
|
127
|
+
Faraday::Utils.URI(path).host
|
128
|
+
]
|
118
129
|
end
|
119
130
|
|
120
|
-
|
131
|
+
stub = Stub.new(host, normalized_path, headers, body, block)
|
132
|
+
(@stack[request_method] ||= []) << stub
|
121
133
|
end
|
122
134
|
|
123
135
|
def matches?(stack, host, path, headers, body)
|
@@ -129,32 +141,42 @@ module Faraday
|
|
129
141
|
end
|
130
142
|
end
|
131
143
|
|
144
|
+
# Stub request
|
145
|
+
# rubocop:disable Style/StructInheritance
|
132
146
|
class Stub < Struct.new(:host, :path, :params, :headers, :body, :block)
|
147
|
+
# rubocop:enable Style/StructInheritance
|
133
148
|
def initialize(host, full, headers, body, block)
|
134
|
-
path, query = full.respond_to?(:split) ? full.split(
|
135
|
-
params =
|
136
|
-
|
137
|
-
|
149
|
+
path, query = full.respond_to?(:split) ? full.split('?') : full
|
150
|
+
params =
|
151
|
+
if query
|
152
|
+
Faraday::Utils.parse_nested_query(query)
|
153
|
+
else
|
154
|
+
{}
|
155
|
+
end
|
156
|
+
|
138
157
|
super(host, path, params, headers, body, block)
|
139
158
|
end
|
140
159
|
|
141
160
|
def matches?(request_host, request_uri, request_headers, request_body)
|
142
161
|
request_path, request_query = request_uri.split('?')
|
143
|
-
request_params =
|
144
|
-
|
145
|
-
|
146
|
-
|
162
|
+
request_params =
|
163
|
+
if request_query
|
164
|
+
Faraday::Utils.parse_nested_query(request_query)
|
165
|
+
else
|
166
|
+
{}
|
167
|
+
end
|
168
|
+
# meta is a hash used as carrier
|
147
169
|
# that will be yielded to consumer block
|
148
170
|
meta = {}
|
149
|
-
|
171
|
+
[(host.nil? || host == request_host) &&
|
150
172
|
path_match?(request_path, meta) &&
|
151
173
|
params_match?(request_params) &&
|
152
174
|
(body.to_s.size.zero? || request_body == body) &&
|
153
|
-
headers_match?(request_headers), meta
|
175
|
+
headers_match?(request_headers), meta]
|
154
176
|
end
|
155
177
|
|
156
178
|
def path_match?(request_path, meta)
|
157
|
-
if path.is_a?
|
179
|
+
if path.is_a?(Regexp)
|
158
180
|
!!(meta[:match_data] = path.match(request_path))
|
159
181
|
else
|
160
182
|
path == request_path
|
@@ -178,7 +200,7 @@ module Faraday
|
|
178
200
|
end
|
179
201
|
end
|
180
202
|
|
181
|
-
def initialize(app, stubs=nil, &block)
|
203
|
+
def initialize(app, stubs = nil, &block)
|
182
204
|
super(app)
|
183
205
|
@stubs = stubs || Stubs.new
|
184
206
|
configure(&block) if block
|
@@ -192,20 +214,31 @@ module Faraday
|
|
192
214
|
super
|
193
215
|
host = env[:url].host
|
194
216
|
normalized_path = Faraday::Utils.normalize_path(env[:url])
|
195
|
-
params_encoder = env.request.params_encoder ||
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
217
|
+
params_encoder = env.request.params_encoder ||
|
218
|
+
Faraday::Utils.default_params_encoder
|
219
|
+
|
220
|
+
stub, meta = stubs.match(env[:method], host, normalized_path,
|
221
|
+
env.request_headers, env[:body])
|
222
|
+
|
223
|
+
unless stub
|
224
|
+
raise Stubs::NotFound, "no stubbed request for #{env[:method]} "\
|
225
|
+
"#{normalized_path} #{env[:body]}"
|
226
|
+
end
|
227
|
+
|
228
|
+
env[:params] = if (query = env[:url].query)
|
229
|
+
params_encoder.decode(query)
|
230
|
+
else
|
231
|
+
{}
|
232
|
+
end
|
233
|
+
block_arity = stub.block.arity
|
234
|
+
status, headers, body =
|
235
|
+
if block_arity >= 0
|
236
|
+
stub.block.call(*[env, meta].take(block_arity))
|
237
|
+
else
|
204
238
|
stub.block.call(env, meta)
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
end
|
239
|
+
end
|
240
|
+
save_response(env, status, body, headers)
|
241
|
+
|
209
242
|
@app.call(env)
|
210
243
|
end
|
211
244
|
end
|