faraday 0.7.4 → 1.0.1
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 +7 -0
- data/CHANGELOG.md +276 -0
- data/LICENSE.md +1 -1
- data/README.md +40 -153
- data/Rakefile +4 -139
- data/examples/client_spec.rb +65 -0
- data/examples/client_test.rb +79 -0
- data/lib/faraday/adapter/em_http.rb +286 -0
- data/lib/faraday/adapter/em_http_ssl_patch.rb +62 -0
- data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +69 -0
- data/lib/faraday/adapter/em_synchrony.rb +120 -36
- data/lib/faraday/adapter/excon.rb +108 -12
- data/lib/faraday/adapter/httpclient.rb +152 -0
- data/lib/faraday/adapter/net_http.rb +187 -43
- data/lib/faraday/adapter/net_http_persistent.rb +91 -0
- data/lib/faraday/adapter/patron.rb +106 -10
- data/lib/faraday/adapter/rack.rb +75 -0
- data/lib/faraday/adapter/test.rb +160 -61
- data/lib/faraday/adapter/typhoeus.rb +7 -46
- data/lib/faraday/adapter.rb +105 -33
- data/lib/faraday/adapter_registry.rb +30 -0
- data/lib/faraday/autoload.rb +95 -0
- data/lib/faraday/connection.rb +525 -157
- data/lib/faraday/dependency_loader.rb +37 -0
- data/lib/faraday/encoders/flat_params_encoder.rb +98 -0
- data/lib/faraday/encoders/nested_params_encoder.rb +171 -0
- data/lib/faraday/error.rb +122 -30
- data/lib/faraday/file_part.rb +128 -0
- data/lib/faraday/logging/formatter.rb +105 -0
- data/lib/faraday/middleware.rb +14 -22
- 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 +28 -0
- data/lib/faraday/options/request_options.rb +22 -0
- data/lib/faraday/options/ssl_options.rb +59 -0
- data/lib/faraday/options.rb +222 -0
- data/lib/faraday/param_part.rb +53 -0
- data/lib/faraday/parameters.rb +5 -0
- data/lib/faraday/rack_builder.rb +248 -0
- data/lib/faraday/request/authorization.rb +55 -0
- data/lib/faraday/request/basic_authentication.rb +20 -0
- data/lib/faraday/request/instrumentation.rb +54 -0
- data/lib/faraday/request/multipart.rb +84 -48
- data/lib/faraday/request/retry.rb +239 -0
- data/lib/faraday/request/token_authentication.rb +20 -0
- data/lib/faraday/request/url_encoded.rb +46 -27
- data/lib/faraday/request.rb +112 -50
- data/lib/faraday/response/logger.rb +24 -25
- data/lib/faraday/response/raise_error.rb +40 -11
- data/lib/faraday/response.rb +44 -35
- data/lib/faraday/utils/headers.rb +139 -0
- data/lib/faraday/utils/params_hash.rb +61 -0
- data/lib/faraday/utils.rb +72 -117
- data/lib/faraday.rb +142 -64
- 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_persistent_spec.rb +57 -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/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 +691 -0
- data/spec/faraday/error_spec.rb +45 -0
- data/spec/faraday/middleware_spec.rb +26 -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 +37 -0
- data/spec/faraday/options/request_options_spec.rb +19 -0
- data/spec/faraday/params_encoders/flat_spec.rb +34 -0
- data/spec/faraday/params_encoders/nested_spec.rb +134 -0
- data/spec/faraday/rack_builder_spec.rb +196 -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 +274 -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 +109 -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 +106 -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 +104 -0
- data/spec/support/shared_examples/params_encoder.rb +18 -0
- data/spec/support/shared_examples/request_method.rb +234 -0
- data/spec/support/streaming_response_checker.rb +35 -0
- data/spec/support/webmock_rack_app.rb +68 -0
- metadata +126 -126
- data/Gemfile +0 -29
- data/config.ru +0 -6
- data/faraday.gemspec +0 -92
- data/lib/faraday/adapter/action_dispatch.rb +0 -29
- data/lib/faraday/builder.rb +0 -160
- data/lib/faraday/request/json.rb +0 -35
- data/lib/faraday/upload_io.rb +0 -23
- data/test/adapters/live_test.rb +0 -205
- data/test/adapters/logger_test.rb +0 -37
- data/test/adapters/net_http_test.rb +0 -33
- data/test/adapters/test_middleware_test.rb +0 -70
- data/test/connection_test.rb +0 -254
- data/test/env_test.rb +0 -158
- data/test/helper.rb +0 -41
- data/test/live_server.rb +0 -45
- data/test/middleware_stack_test.rb +0 -118
- data/test/request_middleware_test.rb +0 -116
- data/test/response_middleware_test.rb +0 -74
data/lib/faraday/adapter/test.rb
CHANGED
|
@@ -1,109 +1,186 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Faraday
|
|
2
4
|
class Adapter
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
5
|
+
# @example
|
|
6
|
+
# test = Faraday::Connection.new do
|
|
7
|
+
# use Faraday::Adapter::Test do |stub|
|
|
8
|
+
# # Define matcher to match the request
|
|
9
|
+
# stub.get '/resource.json' do
|
|
10
|
+
# # return static content
|
|
11
|
+
# [200, {'Content-Type' => 'application/json'}, 'hi world']
|
|
12
|
+
# end
|
|
13
|
+
#
|
|
14
|
+
# # response with content generated based on request
|
|
15
|
+
# stub.get '/showget' do |env|
|
|
16
|
+
# [200, {'Content-Type' => 'text/plain'}, env[:method].to_s]
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# # A regular expression can be used as matching filter
|
|
20
|
+
# stub.get /\A\/items\/(\d+)\z/ do |env, meta|
|
|
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
|
+
# ]
|
|
27
|
+
# end
|
|
7
28
|
# end
|
|
8
29
|
# end
|
|
9
|
-
# end
|
|
10
30
|
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
31
|
+
# resp = test.get '/resource.json'
|
|
32
|
+
# resp.body # => 'hi world'
|
|
33
|
+
#
|
|
34
|
+
# resp = test.get '/showget'
|
|
35
|
+
# resp.body # => 'get'
|
|
13
36
|
#
|
|
37
|
+
# resp = test.get '/items/1'
|
|
38
|
+
# resp.body # => 'showing item: 1'
|
|
39
|
+
#
|
|
40
|
+
# resp = test.get '/items/2'
|
|
41
|
+
# resp.body # => 'showing item: 2'
|
|
14
42
|
class Test < Faraday::Adapter
|
|
15
43
|
attr_accessor :stubs
|
|
16
44
|
|
|
17
|
-
|
|
18
|
-
|
|
45
|
+
# A stack of Stubs
|
|
19
46
|
class Stubs
|
|
20
47
|
class NotFound < StandardError
|
|
21
48
|
end
|
|
22
49
|
|
|
23
50
|
def initialize
|
|
24
|
-
# {:
|
|
25
|
-
@stack
|
|
26
|
-
|
|
51
|
+
# { get: [Stub, Stub] }
|
|
52
|
+
@stack = {}
|
|
53
|
+
@consumed = {}
|
|
54
|
+
yield(self) if block_given?
|
|
27
55
|
end
|
|
28
56
|
|
|
29
57
|
def empty?
|
|
30
58
|
@stack.empty?
|
|
31
59
|
end
|
|
32
60
|
|
|
33
|
-
def match(request_method, path, body)
|
|
34
|
-
return false
|
|
61
|
+
def match(request_method, host, path, headers, body)
|
|
62
|
+
return false unless @stack.key?(request_method)
|
|
63
|
+
|
|
35
64
|
stack = @stack[request_method]
|
|
36
65
|
consumed = (@consumed[request_method] ||= [])
|
|
37
66
|
|
|
38
|
-
|
|
67
|
+
stub, meta = matches?(stack, host, path, headers, body)
|
|
68
|
+
if stub
|
|
39
69
|
consumed << stack.delete(stub)
|
|
40
|
-
stub
|
|
41
|
-
else
|
|
42
|
-
matches?(consumed, path, body)
|
|
70
|
+
return stub, meta
|
|
43
71
|
end
|
|
72
|
+
matches?(consumed, host, path, headers, body)
|
|
44
73
|
end
|
|
45
74
|
|
|
46
|
-
def get(path, &block)
|
|
47
|
-
new_stub(:get, path, &block)
|
|
75
|
+
def get(path, headers = {}, &block)
|
|
76
|
+
new_stub(:get, path, headers, &block)
|
|
48
77
|
end
|
|
49
78
|
|
|
50
|
-
def head(path, &block)
|
|
51
|
-
new_stub(:head, path, &block)
|
|
79
|
+
def head(path, headers = {}, &block)
|
|
80
|
+
new_stub(:head, path, headers, &block)
|
|
52
81
|
end
|
|
53
82
|
|
|
54
|
-
def post(path, body=nil, &block)
|
|
55
|
-
new_stub(:post, path, body, &block)
|
|
83
|
+
def post(path, body = nil, headers = {}, &block)
|
|
84
|
+
new_stub(:post, path, headers, body, &block)
|
|
56
85
|
end
|
|
57
86
|
|
|
58
|
-
def put(path, body=nil, &block)
|
|
59
|
-
new_stub(:put, path, body, &block)
|
|
87
|
+
def put(path, body = nil, headers = {}, &block)
|
|
88
|
+
new_stub(:put, path, headers, body, &block)
|
|
60
89
|
end
|
|
61
90
|
|
|
62
|
-
def
|
|
63
|
-
new_stub(:
|
|
91
|
+
def patch(path, body = nil, headers = {}, &block)
|
|
92
|
+
new_stub(:patch, path, headers, body, &block)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def delete(path, headers = {}, &block)
|
|
96
|
+
new_stub(:delete, path, headers, &block)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def options(path, headers = {}, &block)
|
|
100
|
+
new_stub(:options, path, headers, &block)
|
|
64
101
|
end
|
|
65
102
|
|
|
66
103
|
# Raises an error if any of the stubbed calls have not been made.
|
|
67
104
|
def verify_stubbed_calls
|
|
68
105
|
failed_stubs = []
|
|
69
106
|
@stack.each do |method, stubs|
|
|
70
|
-
|
|
71
|
-
|
|
107
|
+
next if stubs.empty?
|
|
108
|
+
|
|
109
|
+
failed_stubs.concat(
|
|
110
|
+
stubs.map do |stub|
|
|
72
111
|
"Expected #{method} #{stub}."
|
|
73
|
-
|
|
74
|
-
|
|
112
|
+
end
|
|
113
|
+
)
|
|
75
114
|
end
|
|
76
|
-
raise failed_stubs.join(
|
|
115
|
+
raise failed_stubs.join(' ') unless failed_stubs.empty?
|
|
77
116
|
end
|
|
78
117
|
|
|
79
118
|
protected
|
|
80
119
|
|
|
81
|
-
def new_stub(request_method, path, body=nil, &block)
|
|
82
|
-
|
|
120
|
+
def new_stub(request_method, path, headers = {}, body = nil, &block)
|
|
121
|
+
normalized_path, host =
|
|
122
|
+
if path.is_a?(Regexp)
|
|
123
|
+
path
|
|
124
|
+
else
|
|
125
|
+
[
|
|
126
|
+
Faraday::Utils.normalize_path(path),
|
|
127
|
+
Faraday::Utils.URI(path).host
|
|
128
|
+
]
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
stub = Stub.new(host, normalized_path, headers, body, block)
|
|
132
|
+
(@stack[request_method] ||= []) << stub
|
|
83
133
|
end
|
|
84
134
|
|
|
85
|
-
def matches?(stack, path, body)
|
|
86
|
-
stack.
|
|
135
|
+
def matches?(stack, host, path, headers, body)
|
|
136
|
+
stack.each do |stub|
|
|
137
|
+
match_result, meta = stub.matches?(host, path, headers, body)
|
|
138
|
+
return stub, meta if match_result
|
|
139
|
+
end
|
|
140
|
+
nil
|
|
87
141
|
end
|
|
88
142
|
end
|
|
89
143
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
144
|
+
# Stub request
|
|
145
|
+
# rubocop:disable Style/StructInheritance
|
|
146
|
+
class Stub < Struct.new(:host, :path, :params, :headers, :body, :block)
|
|
147
|
+
# rubocop:enable Style/StructInheritance
|
|
148
|
+
def initialize(host, full, headers, body, block)
|
|
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
|
+
|
|
157
|
+
super(host, path, params, headers, body, block)
|
|
97
158
|
end
|
|
98
159
|
|
|
99
|
-
def matches?(request_uri, request_body)
|
|
160
|
+
def matches?(request_host, request_uri, request_headers, request_body)
|
|
100
161
|
request_path, request_query = request_uri.split('?')
|
|
101
|
-
request_params =
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
|
169
|
+
# that will be yielded to consumer block
|
|
170
|
+
meta = {}
|
|
171
|
+
[(host.nil? || host == request_host) &&
|
|
172
|
+
path_match?(request_path, meta) &&
|
|
105
173
|
params_match?(request_params) &&
|
|
106
|
-
(body.to_s.size.zero? || request_body == body)
|
|
174
|
+
(body.to_s.size.zero? || request_body == body) &&
|
|
175
|
+
headers_match?(request_headers), meta]
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def path_match?(request_path, meta)
|
|
179
|
+
if path.is_a?(Regexp)
|
|
180
|
+
!!(meta[:match_data] = path.match(request_path))
|
|
181
|
+
else
|
|
182
|
+
path == request_path
|
|
183
|
+
end
|
|
107
184
|
end
|
|
108
185
|
|
|
109
186
|
def params_match?(request_params)
|
|
@@ -112,34 +189,56 @@ module Faraday
|
|
|
112
189
|
end
|
|
113
190
|
end
|
|
114
191
|
|
|
192
|
+
def headers_match?(request_headers)
|
|
193
|
+
headers.keys.all? do |key|
|
|
194
|
+
request_headers[key] == headers[key]
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
115
198
|
def to_s
|
|
116
199
|
"#{path} #{body}"
|
|
117
200
|
end
|
|
118
201
|
end
|
|
119
202
|
|
|
120
|
-
def initialize(app, stubs=nil, &block)
|
|
203
|
+
def initialize(app, stubs = nil, &block)
|
|
121
204
|
super(app)
|
|
122
205
|
@stubs = stubs || Stubs.new
|
|
123
206
|
configure(&block) if block
|
|
124
207
|
end
|
|
125
208
|
|
|
126
209
|
def configure
|
|
127
|
-
yield
|
|
210
|
+
yield(stubs)
|
|
128
211
|
end
|
|
129
212
|
|
|
130
213
|
def call(env)
|
|
131
214
|
super
|
|
215
|
+
host = env[:url].host
|
|
132
216
|
normalized_path = Faraday::Utils.normalize_path(env[:url])
|
|
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
|
|
238
|
+
stub.block.call(env, meta)
|
|
239
|
+
end
|
|
240
|
+
save_response(env, status, body, headers)
|
|
133
241
|
|
|
134
|
-
if stub = stubs.match(env[:method], normalized_path, env[:body])
|
|
135
|
-
env[:params] = (query = env[:url].query) ?
|
|
136
|
-
Rack::Utils.parse_nested_query(query) :
|
|
137
|
-
{}
|
|
138
|
-
status, headers, body = stub.block.call(env)
|
|
139
|
-
save_response(env, status, body, headers)
|
|
140
|
-
else
|
|
141
|
-
raise Stubs::NotFound, "no stubbed request for #{env[:method]} #{normalized_path} #{env[:body]}"
|
|
142
|
-
end
|
|
143
242
|
@app.call(env)
|
|
144
243
|
end
|
|
145
244
|
end
|
|
@@ -1,54 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Faraday
|
|
2
4
|
class Adapter
|
|
5
|
+
# Typhoeus adapter. This class is just a stub, the real adapter is in
|
|
6
|
+
# https://github.com/typhoeus/typhoeus/blob/master/lib/typhoeus/adapters/faraday.rb
|
|
3
7
|
class Typhoeus < Faraday::Adapter
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def self.setup_parallel_manager(options = {})
|
|
7
|
-
options.empty? ? ::Typhoeus::Hydra.hydra : ::Typhoeus::Hydra.new(options)
|
|
8
|
-
end
|
|
8
|
+
# Needs to define this method in order to support Typhoeus <= 1.3.0
|
|
9
|
+
def call; end
|
|
9
10
|
|
|
10
11
|
dependency 'typhoeus'
|
|
11
|
-
|
|
12
|
-
def call(env)
|
|
13
|
-
super
|
|
14
|
-
|
|
15
|
-
# TODO: support streaming requests
|
|
16
|
-
env[:body] = env[:body].read if env[:body].respond_to? :read
|
|
17
|
-
|
|
18
|
-
req = ::Typhoeus::Request.new env[:url].to_s,
|
|
19
|
-
:method => env[:method],
|
|
20
|
-
:body => env[:body],
|
|
21
|
-
:headers => env[:request_headers],
|
|
22
|
-
:disable_ssl_peer_verification => (env[:ssl] && !env[:ssl].fetch(:verify, true))
|
|
23
|
-
|
|
24
|
-
if ssl = env[:ssl]
|
|
25
|
-
req.ssl_cert = ssl[:client_cert_file] if ssl[:client_cert_file]
|
|
26
|
-
req.ssl_key = ssl[:client_key_file] if ssl[:client_key_file]
|
|
27
|
-
req.ssl_cacert = ssl[:ca_file] if ssl[:ca_file]
|
|
28
|
-
req.ssl_capath = ssl[:ca_path] if ssl[:ca_path]
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
env_req = env[:request]
|
|
32
|
-
req.timeout = req.connect_timeout = (env_req[:timeout] * 1000) if env_req[:timeout]
|
|
33
|
-
req.connect_timeout = (env_req[:open_timeout] * 1000) if env_req[:open_timeout]
|
|
34
|
-
|
|
35
|
-
is_parallel = !!env[:parallel_manager]
|
|
36
|
-
req.on_complete do |resp|
|
|
37
|
-
save_response(env, resp.code, resp.body) do |response_headers|
|
|
38
|
-
response_headers.parse resp.headers
|
|
39
|
-
end
|
|
40
|
-
# in async mode, :response is initialized at this point
|
|
41
|
-
env[:response].finish(env) if is_parallel
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
hydra = env[:parallel_manager] || self.class.setup_parallel_manager
|
|
45
|
-
hydra.queue req
|
|
46
|
-
hydra.run unless is_parallel
|
|
47
|
-
|
|
48
|
-
@app.call env
|
|
49
|
-
rescue Errno::ECONNREFUSED
|
|
50
|
-
raise Error::ConnectionFailed, $!
|
|
51
|
-
end
|
|
12
|
+
dependency 'typhoeus/adapters/faraday'
|
|
52
13
|
end
|
|
53
14
|
end
|
|
54
15
|
end
|
data/lib/faraday/adapter.rb
CHANGED
|
@@ -1,43 +1,115 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Faraday
|
|
2
|
-
class
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
extend
|
|
6
|
-
|
|
7
|
-
autoload_all 'faraday/adapter',
|
|
8
|
-
:ActionDispatch => 'action_dispatch',
|
|
9
|
-
:NetHttp => 'net_http',
|
|
10
|
-
:Typhoeus => 'typhoeus',
|
|
11
|
-
:EMSynchrony => 'em_synchrony',
|
|
12
|
-
:Patron => 'patron',
|
|
13
|
-
:Excon => 'excon',
|
|
14
|
-
:Test => 'test'
|
|
15
|
-
|
|
16
|
-
register_lookup_modules \
|
|
17
|
-
:action_dispatch => :ActionDispatch,
|
|
18
|
-
:test => :Test,
|
|
19
|
-
:net_http => :NetHttp,
|
|
20
|
-
:typhoeus => :Typhoeus,
|
|
21
|
-
:patron => :Patron,
|
|
22
|
-
:em_synchrony => :EMSynchrony,
|
|
23
|
-
:excon => :Excon
|
|
4
|
+
# Base class for all Faraday adapters. Adapters are
|
|
5
|
+
# responsible for fulfilling a Faraday request.
|
|
6
|
+
class Adapter
|
|
7
|
+
extend MiddlewareRegistry
|
|
8
|
+
extend DependencyLoader
|
|
24
9
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
10
|
+
CONTENT_LENGTH = 'Content-Length'
|
|
11
|
+
|
|
12
|
+
register_middleware File.expand_path('adapter', __dir__),
|
|
13
|
+
test: [:Test, 'test'],
|
|
14
|
+
net_http: [:NetHttp, 'net_http'],
|
|
15
|
+
net_http_persistent: [
|
|
16
|
+
:NetHttpPersistent,
|
|
17
|
+
'net_http_persistent'
|
|
18
|
+
],
|
|
19
|
+
typhoeus: [:Typhoeus, 'typhoeus'],
|
|
20
|
+
patron: [:Patron, 'patron'],
|
|
21
|
+
em_synchrony: [:EMSynchrony, 'em_synchrony'],
|
|
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.
|
|
28
|
+
module Parallelism
|
|
29
|
+
attr_writer :supports_parallel
|
|
30
|
+
def supports_parallel?
|
|
31
|
+
@supports_parallel
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def inherited(subclass)
|
|
35
|
+
super
|
|
36
|
+
subclass.supports_parallel = supports_parallel?
|
|
31
37
|
end
|
|
32
38
|
end
|
|
33
39
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
extend Parallelism
|
|
41
|
+
self.supports_parallel = false
|
|
42
|
+
|
|
43
|
+
def initialize(_app = nil, opts = {}, &block)
|
|
44
|
+
@app = ->(env) { env.response }
|
|
45
|
+
@connection_options = opts
|
|
46
|
+
@config_block = block
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Yields or returns an adapter's configured connection. Depends on
|
|
50
|
+
# #build_connection being defined on this adapter.
|
|
51
|
+
#
|
|
52
|
+
# @param env [Faraday::Env, Hash] The env object for a faraday request.
|
|
53
|
+
#
|
|
54
|
+
# @return The return value of the given block, or the HTTP connection object
|
|
55
|
+
# if no block is given.
|
|
56
|
+
def connection(env)
|
|
57
|
+
conn = build_connection(env)
|
|
58
|
+
return conn unless block_given?
|
|
59
|
+
|
|
60
|
+
yield conn
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Close any persistent connections. The adapter should still be usable
|
|
64
|
+
# after calling close.
|
|
65
|
+
def close
|
|
66
|
+
# Possible implementation:
|
|
67
|
+
# @app.close if @app.respond_to?(:close)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def call(env)
|
|
71
|
+
env.clear_body if env.needs_body?
|
|
72
|
+
env.response = Response.new
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
def save_response(env, status, body, headers = nil, reason_phrase = nil)
|
|
78
|
+
env.status = status
|
|
79
|
+
env.body = body
|
|
80
|
+
env.reason_phrase = reason_phrase&.to_s&.strip
|
|
81
|
+
env.response_headers = Utils::Headers.new.tap do |response_headers|
|
|
38
82
|
response_headers.update headers unless headers.nil?
|
|
39
|
-
yield
|
|
83
|
+
yield(response_headers) if block_given?
|
|
40
84
|
end
|
|
85
|
+
|
|
86
|
+
env.response.finish(env) unless env.parallel?
|
|
87
|
+
env.response
|
|
41
88
|
end
|
|
89
|
+
|
|
90
|
+
# Fetches either a read, write, or open timeout setting. Defaults to the
|
|
91
|
+
# :timeout value if a more specific one is not given.
|
|
92
|
+
#
|
|
93
|
+
# @param type [Symbol] Describes which timeout setting to get: :read,
|
|
94
|
+
# :write, or :open.
|
|
95
|
+
# @param options [Hash] Hash containing Symbol keys like :timeout,
|
|
96
|
+
# :read_timeout, :write_timeout, :open_timeout, or
|
|
97
|
+
# :timeout
|
|
98
|
+
#
|
|
99
|
+
# @return [Integer, nil] Timeout duration in seconds, or nil if no timeout
|
|
100
|
+
# has been set.
|
|
101
|
+
def request_timeout(type, options)
|
|
102
|
+
key = TIMEOUT_KEYS.fetch(type) do
|
|
103
|
+
msg = "Expected :read, :write, :open. Got #{type.inspect} :("
|
|
104
|
+
raise ArgumentError, msg
|
|
105
|
+
end
|
|
106
|
+
options[key] || options[:timeout]
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
TIMEOUT_KEYS = {
|
|
110
|
+
read: :read_timeout,
|
|
111
|
+
open: :open_timeout,
|
|
112
|
+
write: :write_timeout
|
|
113
|
+
}.freeze
|
|
42
114
|
end
|
|
43
115
|
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'monitor'
|
|
4
|
+
|
|
5
|
+
module Faraday
|
|
6
|
+
# AdapterRegistry registers adapter class names so they can be looked up by a
|
|
7
|
+
# String or Symbol name.
|
|
8
|
+
class AdapterRegistry
|
|
9
|
+
def initialize
|
|
10
|
+
@lock = Monitor.new
|
|
11
|
+
@constants = {}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def get(name)
|
|
15
|
+
klass = @lock.synchronize do
|
|
16
|
+
@constants[name]
|
|
17
|
+
end
|
|
18
|
+
return klass if klass
|
|
19
|
+
|
|
20
|
+
Object.const_get(name).tap { |c| set(c, name) }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def set(klass, name = nil)
|
|
24
|
+
name ||= klass.to_s
|
|
25
|
+
@lock.synchronize do
|
|
26
|
+
@constants[name] = klass
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Faraday
|
|
4
|
+
# Adds the ability for other modules to manage autoloadable
|
|
5
|
+
# constants.
|
|
6
|
+
#
|
|
7
|
+
# @api private
|
|
8
|
+
module AutoloadHelper
|
|
9
|
+
# Registers the constants to be auto loaded.
|
|
10
|
+
#
|
|
11
|
+
# @param prefix [String] The require prefix. If the path is inside Faraday,
|
|
12
|
+
# then it will be prefixed with the root path of this loaded
|
|
13
|
+
# Faraday version.
|
|
14
|
+
# @param options [{ Symbol => String }] library names.
|
|
15
|
+
#
|
|
16
|
+
# @example
|
|
17
|
+
#
|
|
18
|
+
# Faraday.autoload_all 'faraday/foo',
|
|
19
|
+
# Bar: 'bar'
|
|
20
|
+
#
|
|
21
|
+
# # requires faraday/foo/bar to load Faraday::Bar.
|
|
22
|
+
# Faraday::Bar
|
|
23
|
+
#
|
|
24
|
+
# @return [void]
|
|
25
|
+
def autoload_all(prefix, options)
|
|
26
|
+
if prefix =~ %r{^faraday(/|$)}i
|
|
27
|
+
prefix = File.join(Faraday.root_path, prefix)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
options.each do |const_name, path|
|
|
31
|
+
autoload const_name, File.join(prefix, path)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Loads each autoloaded constant. If thread safety is a concern,
|
|
36
|
+
# wrap this in a Mutex.
|
|
37
|
+
#
|
|
38
|
+
# @return [void]
|
|
39
|
+
def load_autoloaded_constants
|
|
40
|
+
constants.each do |const|
|
|
41
|
+
const_get(const) if autoload?(const)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Filters the module's contents with those that have been already
|
|
46
|
+
# autoloaded.
|
|
47
|
+
#
|
|
48
|
+
# @return [Array<Class, Module>]
|
|
49
|
+
def all_loaded_constants
|
|
50
|
+
constants
|
|
51
|
+
.map { |c| const_get(c) }
|
|
52
|
+
.select { |a| a.respond_to?(:loaded?) && a.loaded? }
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Adapter is the base class for all Faraday adapters.
|
|
57
|
+
# @see lib/faraday/adapter.rb Original class location
|
|
58
|
+
class Adapter
|
|
59
|
+
extend AutoloadHelper
|
|
60
|
+
autoload_all 'faraday/adapter',
|
|
61
|
+
NetHttp: 'net_http',
|
|
62
|
+
NetHttpPersistent: 'net_http_persistent',
|
|
63
|
+
EMSynchrony: 'em_synchrony',
|
|
64
|
+
EMHttp: 'em_http',
|
|
65
|
+
Typhoeus: 'typhoeus',
|
|
66
|
+
Patron: 'patron',
|
|
67
|
+
Excon: 'excon',
|
|
68
|
+
Test: 'test',
|
|
69
|
+
Rack: 'rack',
|
|
70
|
+
HTTPClient: 'httpclient'
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Request represents a single HTTP request for a Faraday adapter to make.
|
|
74
|
+
# @see lib/faraday/request.rb Original class location
|
|
75
|
+
class Request
|
|
76
|
+
extend AutoloadHelper
|
|
77
|
+
autoload_all 'faraday/request',
|
|
78
|
+
UrlEncoded: 'url_encoded',
|
|
79
|
+
Multipart: 'multipart',
|
|
80
|
+
Retry: 'retry',
|
|
81
|
+
Authorization: 'authorization',
|
|
82
|
+
BasicAuthentication: 'basic_authentication',
|
|
83
|
+
TokenAuthentication: 'token_authentication',
|
|
84
|
+
Instrumentation: 'instrumentation'
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Response represents the returned value of a sent Faraday request.
|
|
88
|
+
# @see lib/faraday/response.rb Original class location
|
|
89
|
+
class Response
|
|
90
|
+
extend AutoloadHelper
|
|
91
|
+
autoload_all 'faraday/response',
|
|
92
|
+
RaiseError: 'raise_error',
|
|
93
|
+
Logger: 'logger'
|
|
94
|
+
end
|
|
95
|
+
end
|