faraday 0.9.1 → 0.17.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +212 -0
- data/LICENSE.md +1 -1
- data/README.md +203 -28
- data/Rakefile +6 -64
- data/lib/faraday/adapter/em_http.rb +17 -11
- data/lib/faraday/adapter/em_http_ssl_patch.rb +1 -1
- data/lib/faraday/adapter/em_synchrony.rb +19 -5
- data/lib/faraday/adapter/excon.rb +13 -11
- data/lib/faraday/adapter/httpclient.rb +31 -9
- data/lib/faraday/adapter/net_http.rb +37 -14
- data/lib/faraday/adapter/net_http_persistent.rb +37 -17
- data/lib/faraday/adapter/patron.rb +44 -21
- data/lib/faraday/adapter/rack.rb +1 -1
- data/lib/faraday/adapter/test.rb +79 -28
- data/lib/faraday/adapter/typhoeus.rb +4 -115
- data/lib/faraday/adapter.rb +10 -1
- data/lib/faraday/autoload.rb +1 -1
- data/lib/faraday/connection.rb +72 -20
- data/lib/faraday/deprecate.rb +109 -0
- data/lib/faraday/error.rb +132 -27
- data/lib/faraday/options.rb +45 -22
- data/lib/faraday/parameters.rb +56 -39
- data/lib/faraday/rack_builder.rb +29 -4
- data/lib/faraday/request/authorization.rb +1 -2
- data/lib/faraday/request/multipart.rb +7 -2
- data/lib/faraday/request/retry.rb +84 -19
- data/lib/faraday/request.rb +22 -0
- data/lib/faraday/response/logger.rb +29 -8
- data/lib/faraday/response/raise_error.rb +7 -3
- data/lib/faraday/response.rb +9 -5
- data/lib/faraday/utils.rb +32 -3
- data/lib/faraday.rb +15 -36
- data/spec/faraday/deprecate_spec.rb +147 -0
- data/spec/faraday/error_spec.rb +102 -0
- data/spec/faraday/response/raise_error_spec.rb +106 -0
- data/spec/spec_helper.rb +105 -0
- data/test/adapters/em_http_test.rb +10 -0
- data/test/adapters/em_synchrony_test.rb +22 -10
- data/test/adapters/excon_test.rb +10 -0
- data/test/adapters/httpclient_test.rb +14 -1
- data/test/adapters/integration.rb +17 -8
- data/test/adapters/logger_test.rb +65 -11
- data/test/adapters/net_http_persistent_test.rb +96 -2
- data/test/adapters/net_http_test.rb +67 -2
- data/test/adapters/patron_test.rb +28 -8
- data/test/adapters/rack_test.rb +8 -1
- data/test/adapters/test_middleware_test.rb +46 -3
- data/test/adapters/typhoeus_test.rb +19 -9
- data/test/composite_read_io_test.rb +16 -18
- data/test/connection_test.rb +294 -78
- data/test/env_test.rb +55 -5
- data/test/helper.rb +11 -17
- data/test/middleware/retry_test.rb +115 -10
- data/test/middleware_stack_test.rb +97 -10
- data/test/options_test.rb +97 -16
- data/test/parameters_test.rb +94 -1
- data/test/request_middleware_test.rb +24 -40
- data/test/response_middleware_test.rb +4 -4
- data/test/utils_test.rb +40 -0
- metadata +21 -66
- data/.document +0 -6
- data/CONTRIBUTING.md +0 -36
- data/Gemfile +0 -25
- data/faraday.gemspec +0 -34
- 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
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
1
3
|
module Faraday
|
2
4
|
# Catches exceptions and retries each request a limited number of times.
|
3
5
|
#
|
@@ -10,7 +12,7 @@ module Faraday
|
|
10
12
|
#
|
11
13
|
# Faraday.new do |conn|
|
12
14
|
# conn.request :retry, max: 2, interval: 0.05,
|
13
|
-
# interval_randomness: 0.5, backoff_factor: 2
|
15
|
+
# interval_randomness: 0.5, backoff_factor: 2,
|
14
16
|
# exceptions: [CustomException, 'Timeout::Error']
|
15
17
|
# conn.adapter ...
|
16
18
|
# end
|
@@ -19,15 +21,19 @@ module Faraday
|
|
19
21
|
# interval that is random between 0.1 and 0.15
|
20
22
|
#
|
21
23
|
class Request::Retry < Faraday::Middleware
|
22
|
-
|
24
|
+
DEFAULT_EXCEPTIONS = [Errno::ETIMEDOUT, 'Timeout::Error',
|
25
|
+
Faraday::TimeoutError, Faraday::RetriableResponse
|
26
|
+
].freeze
|
23
27
|
IDEMPOTENT_METHODS = [:delete, :get, :head, :options, :put]
|
24
28
|
|
25
|
-
class Options < Faraday::Options.new(:max, :interval, :
|
26
|
-
:exceptions, :methods, :retry_if
|
29
|
+
class Options < Faraday::Options.new(:max, :interval, :max_interval, :interval_randomness,
|
30
|
+
:backoff_factor, :exceptions, :methods, :retry_if, :retry_block,
|
31
|
+
:retry_statuses)
|
32
|
+
|
27
33
|
DEFAULT_CHECK = lambda { |env,exception| false }
|
28
34
|
|
29
35
|
def self.from(value)
|
30
|
-
if
|
36
|
+
if Integer === value
|
31
37
|
new(value)
|
32
38
|
else
|
33
39
|
super(value)
|
@@ -42,8 +48,12 @@ module Faraday
|
|
42
48
|
(self[:interval] ||= 0).to_f
|
43
49
|
end
|
44
50
|
|
51
|
+
def max_interval
|
52
|
+
(self[:max_interval] ||= Float::MAX).to_f
|
53
|
+
end
|
54
|
+
|
45
55
|
def interval_randomness
|
46
|
-
(self[:interval_randomness] ||= 0).
|
56
|
+
(self[:interval_randomness] ||= 0).to_f
|
47
57
|
end
|
48
58
|
|
49
59
|
def backoff_factor
|
@@ -51,8 +61,7 @@ module Faraday
|
|
51
61
|
end
|
52
62
|
|
53
63
|
def exceptions
|
54
|
-
Array(self[:exceptions] ||=
|
55
|
-
Error::TimeoutError])
|
64
|
+
Array(self[:exceptions] ||= DEFAULT_EXCEPTIONS)
|
56
65
|
end
|
57
66
|
|
58
67
|
def methods
|
@@ -63,6 +72,13 @@ module Faraday
|
|
63
72
|
self[:retry_if] ||= DEFAULT_CHECK
|
64
73
|
end
|
65
74
|
|
75
|
+
def retry_block
|
76
|
+
self[:retry_block] ||= Proc.new {}
|
77
|
+
end
|
78
|
+
|
79
|
+
def retry_statuses
|
80
|
+
Array(self[:retry_statuses] ||= [])
|
81
|
+
end
|
66
82
|
end
|
67
83
|
|
68
84
|
# Public: Initialize middleware
|
@@ -73,13 +89,14 @@ module Faraday
|
|
73
89
|
# interval_randomness - The maximum random interval amount expressed
|
74
90
|
# as a float between 0 and 1 to use in addition to the
|
75
91
|
# interval. (default: 0)
|
92
|
+
# max_interval - An upper limit for the interval (default: Float::MAX)
|
76
93
|
# backoff_factor - The amount to multiple each successive retry's
|
77
94
|
# interval amount by in order to provide backoff
|
78
95
|
# (default: 1)
|
79
96
|
# exceptions - The list of exceptions to handle. Exceptions can be
|
80
97
|
# given as Class, Module, or String. (default:
|
81
|
-
# [Errno::ETIMEDOUT, Timeout::Error,
|
82
|
-
#
|
98
|
+
# [Errno::ETIMEDOUT, 'Timeout::Error',
|
99
|
+
# Faraday::TimeoutError, Faraday::RetriableResponse])
|
83
100
|
# methods - A list of HTTP methods to retry without calling retry_if. Pass
|
84
101
|
# an empty Array to call retry_if for all exceptions.
|
85
102
|
# (defaults to the idempotent HTTP methods in IDEMPOTENT_METHODS)
|
@@ -89,17 +106,21 @@ module Faraday
|
|
89
106
|
# if the exception produced is non-recoverable or if the
|
90
107
|
# the HTTP method called is not idempotent.
|
91
108
|
# (defaults to return false)
|
109
|
+
# retry_block - block that is executed after every retry. Request environment, middleware options,
|
110
|
+
# current number of retries and the exception is passed to the block as parameters.
|
92
111
|
def initialize(app, options = nil)
|
93
112
|
super(app)
|
94
113
|
@options = Options.from(options)
|
95
114
|
@errmatch = build_exception_matcher(@options.exceptions)
|
96
115
|
end
|
97
116
|
|
98
|
-
def
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
117
|
+
def calculate_sleep_amount(retries, env)
|
118
|
+
retry_after = calculate_retry_after(env)
|
119
|
+
retry_interval = calculate_retry_interval(retries)
|
120
|
+
|
121
|
+
return if retry_after && retry_after > @options.max_interval
|
122
|
+
|
123
|
+
retry_after && retry_after >= retry_interval ? retry_after : retry_interval
|
103
124
|
end
|
104
125
|
|
105
126
|
def call(env)
|
@@ -107,14 +128,25 @@ module Faraday
|
|
107
128
|
request_body = env[:body]
|
108
129
|
begin
|
109
130
|
env[:body] = request_body # after failure env[:body] is set to the response body
|
110
|
-
@app.call(env)
|
131
|
+
@app.call(env).tap do |resp|
|
132
|
+
raise Faraday::RetriableResponse.new(nil, resp) if @options.retry_statuses.include?(resp.status)
|
133
|
+
end
|
111
134
|
rescue @errmatch => exception
|
112
135
|
if retries > 0 && retry_request?(env, exception)
|
113
136
|
retries -= 1
|
114
|
-
|
115
|
-
|
137
|
+
rewind_files(request_body)
|
138
|
+
@options.retry_block.call(env, @options, retries, exception)
|
139
|
+
if (sleep_amount = calculate_sleep_amount(retries + 1, env))
|
140
|
+
sleep sleep_amount
|
141
|
+
retry
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
if exception.is_a?(Faraday::RetriableResponse)
|
146
|
+
exception.response
|
147
|
+
else
|
148
|
+
raise
|
116
149
|
end
|
117
|
-
raise
|
118
150
|
end
|
119
151
|
end
|
120
152
|
|
@@ -144,5 +176,38 @@ module Faraday
|
|
144
176
|
@options.methods.include?(env[:method]) || @options.retry_if.call(env, exception)
|
145
177
|
end
|
146
178
|
|
179
|
+
def rewind_files(body)
|
180
|
+
return unless body.is_a?(Hash)
|
181
|
+
body.each do |_, value|
|
182
|
+
if value.is_a? UploadIO
|
183
|
+
value.rewind
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
# MDN spec for Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
|
189
|
+
def calculate_retry_after(env)
|
190
|
+
response_headers = env[:response_headers]
|
191
|
+
return unless response_headers
|
192
|
+
|
193
|
+
retry_after_value = env[:response_headers]["Retry-After"]
|
194
|
+
|
195
|
+
# Try to parse date from the header value
|
196
|
+
begin
|
197
|
+
datetime = DateTime.rfc2822(retry_after_value)
|
198
|
+
datetime.to_time - Time.now.utc
|
199
|
+
rescue ArgumentError
|
200
|
+
retry_after_value.to_f
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def calculate_retry_interval(retries)
|
205
|
+
retry_index = @options.max - retries
|
206
|
+
current_interval = @options.interval * (@options.backoff_factor ** retry_index)
|
207
|
+
current_interval = [current_interval, @options.max_interval].min
|
208
|
+
random_interval = rand * @options.interval_randomness.to_f * @options.interval
|
209
|
+
|
210
|
+
current_interval + random_interval
|
211
|
+
end
|
147
212
|
end
|
148
213
|
end
|
data/lib/faraday/request.rb
CHANGED
@@ -52,6 +52,8 @@ module Faraday
|
|
52
52
|
path.query = nil
|
53
53
|
end
|
54
54
|
else
|
55
|
+
anchor_index = path.index('#')
|
56
|
+
path = path.slice(0, anchor_index) unless anchor_index.nil?
|
55
57
|
path, query = path.split('?', 2)
|
56
58
|
end
|
57
59
|
self.path = path
|
@@ -67,6 +69,26 @@ module Faraday
|
|
67
69
|
headers[key] = value
|
68
70
|
end
|
69
71
|
|
72
|
+
def marshal_dump
|
73
|
+
{
|
74
|
+
:method => method,
|
75
|
+
:body => body,
|
76
|
+
:headers => headers,
|
77
|
+
:path => path,
|
78
|
+
:params => params,
|
79
|
+
:options => options
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
def marshal_load(serialised)
|
84
|
+
self.method = serialised[:method]
|
85
|
+
self.body = serialised[:body]
|
86
|
+
self.headers = serialised[:headers]
|
87
|
+
self.path = serialised[:path]
|
88
|
+
self.params = serialised[:params]
|
89
|
+
self.options = serialised[:options]
|
90
|
+
end
|
91
|
+
|
70
92
|
# ENV Keys
|
71
93
|
# :method - a symbolized request method (:get, :post)
|
72
94
|
# :body - the request body that will eventually be converted to a string.
|
@@ -4,30 +4,36 @@ module Faraday
|
|
4
4
|
class Response::Logger < Response::Middleware
|
5
5
|
extend Forwardable
|
6
6
|
|
7
|
-
DEFAULT_OPTIONS = { :bodies => false }
|
7
|
+
DEFAULT_OPTIONS = { :headers => true, :bodies => false }
|
8
8
|
|
9
9
|
def initialize(app, logger = nil, options = {})
|
10
10
|
super(app)
|
11
11
|
@logger = logger || begin
|
12
12
|
require 'logger'
|
13
|
-
::Logger.new(
|
13
|
+
::Logger.new($stdout)
|
14
14
|
end
|
15
|
+
@filter = []
|
15
16
|
@options = DEFAULT_OPTIONS.merge(options)
|
17
|
+
yield self if block_given?
|
16
18
|
end
|
17
19
|
|
18
20
|
def_delegators :@logger, :debug, :info, :warn, :error, :fatal
|
19
21
|
|
20
22
|
def call(env)
|
21
|
-
info "#{env.method} #{env.url.to_s}"
|
22
|
-
debug('request') { dump_headers env.request_headers }
|
23
|
-
debug('request') { dump_body(env[:body]) } if env[:body] && log_body?(:request)
|
23
|
+
info('request') { "#{env.method.upcase} #{apply_filters(env.url.to_s)}" }
|
24
|
+
debug('request') { apply_filters( dump_headers env.request_headers ) } if log_headers?(:request)
|
25
|
+
debug('request') { apply_filters( dump_body(env[:body]) ) } if env[:body] && log_body?(:request)
|
24
26
|
super
|
25
27
|
end
|
26
28
|
|
27
29
|
def on_complete(env)
|
28
|
-
info('
|
29
|
-
debug('response') { dump_headers env.response_headers }
|
30
|
-
debug('response') { dump_body env[:body] } if env[:body] && log_body?(:response)
|
30
|
+
info('response') { "Status #{env.status.to_s}" }
|
31
|
+
debug('response') { apply_filters( dump_headers env.response_headers ) } if log_headers?(:response)
|
32
|
+
debug('response') { apply_filters( dump_body env[:body] ) } if env[:body] && log_body?(:response)
|
33
|
+
end
|
34
|
+
|
35
|
+
def filter(filter_word, filter_replacement)
|
36
|
+
@filter.push([ filter_word, filter_replacement ])
|
31
37
|
end
|
32
38
|
|
33
39
|
private
|
@@ -49,11 +55,26 @@ module Faraday
|
|
49
55
|
body.pretty_inspect
|
50
56
|
end
|
51
57
|
|
58
|
+
def log_headers?(type)
|
59
|
+
case @options[:headers]
|
60
|
+
when Hash then @options[:headers][type]
|
61
|
+
else @options[:headers]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
52
65
|
def log_body?(type)
|
53
66
|
case @options[:bodies]
|
54
67
|
when Hash then @options[:bodies][type]
|
55
68
|
else @options[:bodies]
|
56
69
|
end
|
57
70
|
end
|
71
|
+
|
72
|
+
def apply_filters(output)
|
73
|
+
@filter.each do |pattern, replacement|
|
74
|
+
output = output.to_s.gsub(pattern, replacement)
|
75
|
+
end
|
76
|
+
output
|
77
|
+
end
|
78
|
+
|
58
79
|
end
|
59
80
|
end
|
@@ -5,12 +5,16 @@ module Faraday
|
|
5
5
|
def on_complete(env)
|
6
6
|
case env[:status]
|
7
7
|
when 404
|
8
|
-
raise Faraday::
|
8
|
+
raise Faraday::ResourceNotFound, response_values(env)
|
9
9
|
when 407
|
10
10
|
# mimic the behavior that we get with proxy requests with HTTPS
|
11
|
-
raise Faraday::
|
11
|
+
raise Faraday::ConnectionFailed.new(
|
12
|
+
%{407 "Proxy Authentication Required "},
|
13
|
+
response_values(env))
|
12
14
|
when ClientErrorStatuses
|
13
|
-
raise Faraday::
|
15
|
+
raise Faraday::ClientError, response_values(env)
|
16
|
+
when nil
|
17
|
+
raise Faraday::NilStatusError, response_values(env)
|
14
18
|
end
|
15
19
|
end
|
16
20
|
|
data/lib/faraday/response.rb
CHANGED
@@ -37,6 +37,10 @@ module Faraday
|
|
37
37
|
finished? ? env.status : nil
|
38
38
|
end
|
39
39
|
|
40
|
+
def reason_phrase
|
41
|
+
finished? ? env.reason_phrase : nil
|
42
|
+
end
|
43
|
+
|
40
44
|
def headers
|
41
45
|
finished? ? env.response_headers : {}
|
42
46
|
end
|
@@ -50,9 +54,9 @@ module Faraday
|
|
50
54
|
!!env
|
51
55
|
end
|
52
56
|
|
53
|
-
def on_complete
|
54
|
-
if
|
55
|
-
@on_complete_callbacks <<
|
57
|
+
def on_complete(&block)
|
58
|
+
if !finished?
|
59
|
+
@on_complete_callbacks << block
|
56
60
|
else
|
57
61
|
yield(env)
|
58
62
|
end
|
@@ -61,8 +65,8 @@ module Faraday
|
|
61
65
|
|
62
66
|
def finish(env)
|
63
67
|
raise "response already finished" if finished?
|
64
|
-
@
|
65
|
-
@
|
68
|
+
@env = env.is_a?(Env) ? env : Env.from(env)
|
69
|
+
@on_complete_callbacks.each { |callback| callback.call(@env) }
|
66
70
|
return self
|
67
71
|
end
|
68
72
|
|
data/lib/faraday/utils.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'thread'
|
2
|
-
Faraday.require_libs 'parameters'
|
3
2
|
|
4
3
|
module Faraday
|
5
4
|
module Utils
|
@@ -11,12 +10,28 @@ module Faraday
|
|
11
10
|
new(value)
|
12
11
|
end
|
13
12
|
|
13
|
+
def self.allocate
|
14
|
+
new_self = super
|
15
|
+
new_self.initialize_names
|
16
|
+
new_self
|
17
|
+
end
|
18
|
+
|
14
19
|
def initialize(hash = nil)
|
15
20
|
super()
|
16
21
|
@names = {}
|
17
22
|
self.update(hash || {})
|
18
23
|
end
|
19
24
|
|
25
|
+
def initialize_names
|
26
|
+
@names = {}
|
27
|
+
end
|
28
|
+
|
29
|
+
# on dup/clone, we need to duplicate @names hash
|
30
|
+
def initialize_copy(other)
|
31
|
+
super
|
32
|
+
@names = other.names.dup
|
33
|
+
end
|
34
|
+
|
20
35
|
# need to synchronize concurrent writes to the shared KeyMap
|
21
36
|
keymap_mutex = Mutex.new
|
22
37
|
|
@@ -81,6 +96,7 @@ module Faraday
|
|
81
96
|
|
82
97
|
def replace(other)
|
83
98
|
clear
|
99
|
+
@names.clear
|
84
100
|
self.update other
|
85
101
|
self
|
86
102
|
end
|
@@ -89,9 +105,16 @@ module Faraday
|
|
89
105
|
|
90
106
|
def parse(header_string)
|
91
107
|
return unless header_string && !header_string.empty?
|
92
|
-
|
108
|
+
|
109
|
+
headers = header_string.split(/\r\n/)
|
110
|
+
|
111
|
+
# Find the last set of response headers.
|
112
|
+
start_index = headers.rindex { |x| x.match(/^HTTP\//) } || 0
|
113
|
+
last_response = headers.slice(start_index, headers.size)
|
114
|
+
|
115
|
+
last_response.
|
93
116
|
tap { |a| a.shift if a.first.index('HTTP/') == 0 }. # drop the HTTP status line
|
94
|
-
map { |h| h.split(/:\s
|
117
|
+
map { |h| h.split(/:\s*/, 2) }.reject { |p| p[0].nil? }. # split key and value, ignore blank lines
|
95
118
|
each { |key, value|
|
96
119
|
# join multiple values with a comma
|
97
120
|
if self[key]
|
@@ -101,6 +124,12 @@ module Faraday
|
|
101
124
|
end
|
102
125
|
}
|
103
126
|
end
|
127
|
+
|
128
|
+
protected
|
129
|
+
|
130
|
+
def names
|
131
|
+
@names
|
132
|
+
end
|
104
133
|
end
|
105
134
|
|
106
135
|
# hash with stringified keys
|
data/lib/faraday.rb
CHANGED
@@ -14,7 +14,7 @@ require 'forwardable'
|
|
14
14
|
# conn.get '/'
|
15
15
|
#
|
16
16
|
module Faraday
|
17
|
-
VERSION = "0.
|
17
|
+
VERSION = "0.17.4"
|
18
18
|
|
19
19
|
class << self
|
20
20
|
# Public: Gets or sets the root path that Faraday is being loaded from.
|
@@ -34,8 +34,8 @@ module Faraday
|
|
34
34
|
# Faraday.get "https://faraday.com"
|
35
35
|
attr_writer :default_connection
|
36
36
|
|
37
|
-
# Public:
|
38
|
-
|
37
|
+
# Public: Tells faraday to ignore the environment proxy (http_proxy).
|
38
|
+
attr_accessor :ignore_env_proxy
|
39
39
|
|
40
40
|
# Public: Initializes a new Faraday::Connection.
|
41
41
|
#
|
@@ -64,9 +64,8 @@ module Faraday
|
|
64
64
|
# :params => {:page => 1}
|
65
65
|
#
|
66
66
|
# Returns a Faraday::Connection.
|
67
|
-
def new(url = nil, options = nil)
|
68
|
-
|
69
|
-
options = options ? default_connection_options.merge(options) : default_connection_options.dup
|
67
|
+
def new(url = nil, options = nil, &block)
|
68
|
+
options = options ? default_connection_options.merge(options) : default_connection_options
|
70
69
|
Faraday::Connection.new(url, options, &block)
|
71
70
|
end
|
72
71
|
|
@@ -92,6 +91,10 @@ module Faraday
|
|
92
91
|
|
93
92
|
alias require_lib require_libs
|
94
93
|
|
94
|
+
def respond_to?(symbol, include_private = false)
|
95
|
+
default_connection.respond_to?(symbol, include_private) || super
|
96
|
+
end
|
97
|
+
|
95
98
|
private
|
96
99
|
# Internal: Proxies method calls on the Faraday constant to
|
97
100
|
# #default_connection.
|
@@ -100,6 +103,7 @@ module Faraday
|
|
100
103
|
end
|
101
104
|
end
|
102
105
|
|
106
|
+
self.ignore_env_proxy = false
|
103
107
|
self.root_path = File.expand_path "..", __FILE__
|
104
108
|
self.lib_path = File.expand_path "../faraday", __FILE__
|
105
109
|
self.default_adapter = :net_http
|
@@ -108,7 +112,7 @@ module Faraday
|
|
108
112
|
#
|
109
113
|
# Returns a Faraday::Connection, configured with the #default_adapter.
|
110
114
|
def self.default_connection
|
111
|
-
@default_connection ||= Connection.new
|
115
|
+
@default_connection ||= Connection.new(default_connection_options)
|
112
116
|
end
|
113
117
|
|
114
118
|
# Gets the default connection options used when calling Faraday#new.
|
@@ -118,13 +122,10 @@ module Faraday
|
|
118
122
|
@default_connection_options ||= ConnectionOptions.new
|
119
123
|
end
|
120
124
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
rescue LoadError
|
126
|
-
warn "Faraday: you may want to install system_timer for reliable timeouts"
|
127
|
-
end
|
125
|
+
# Public: Sets the default options used when calling Faraday#new.
|
126
|
+
def self.default_connection_options=(options)
|
127
|
+
@default_connection = nil
|
128
|
+
@default_connection_options = ConnectionOptions.from(options)
|
128
129
|
end
|
129
130
|
|
130
131
|
unless const_defined? :Timer
|
@@ -244,25 +245,3 @@ module Faraday
|
|
244
245
|
require_lib 'autoload'
|
245
246
|
end
|
246
247
|
end
|
247
|
-
|
248
|
-
# not pulling in active-support JUST for this method. And I love this method.
|
249
|
-
class Object
|
250
|
-
# The primary purpose of this method is to "tap into" a method chain,
|
251
|
-
# in order to perform operations on intermediate results within the chain.
|
252
|
-
#
|
253
|
-
# Examples
|
254
|
-
#
|
255
|
-
# (1..10).tap { |x| puts "original: #{x.inspect}" }.to_a.
|
256
|
-
# tap { |x| puts "array: #{x.inspect}" }.
|
257
|
-
# select { |x| x%2 == 0 }.
|
258
|
-
# tap { |x| puts "evens: #{x.inspect}" }.
|
259
|
-
# map { |x| x*x }.
|
260
|
-
# tap { |x| puts "squares: #{x.inspect}" }
|
261
|
-
#
|
262
|
-
# Yields self.
|
263
|
-
# Returns self.
|
264
|
-
def tap
|
265
|
-
yield(self)
|
266
|
-
self
|
267
|
-
end unless Object.respond_to?(:tap)
|
268
|
-
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Faraday::DeprecatedClass do
|
4
|
+
class SampleClass < StandardError
|
5
|
+
attr_accessor :foo
|
6
|
+
|
7
|
+
def initialize(foo = nil)
|
8
|
+
@foo = foo || :foo
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
SampleDeprecatedClass = Faraday::DeprecatedClass.proxy_class(SampleClass)
|
13
|
+
|
14
|
+
it 'does not raise error for deprecated classes but prints an error message' do
|
15
|
+
error_message, foobar = with_warn_squelching { SampleDeprecatedClass.new(:foo_bar) }
|
16
|
+
expect(foobar).to be_a(SampleClass)
|
17
|
+
expect(foobar.foo).to eq(:foo_bar)
|
18
|
+
expect(error_message).to match(
|
19
|
+
Regexp.new(
|
20
|
+
'NOTE: SampleDeprecatedClass.new is deprecated; '\
|
21
|
+
'use SampleClass.new instead. It will be removed in or after version 1.0'
|
22
|
+
)
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'does not raise an error for inherited error-namespaced classes but prints an error message' do
|
27
|
+
error_message, = with_warn_squelching { Class.new(SampleDeprecatedClass) }
|
28
|
+
|
29
|
+
expect(error_message).to match(
|
30
|
+
Regexp.new(
|
31
|
+
'NOTE: Inheriting SampleDeprecatedClass is deprecated; '\
|
32
|
+
'use SampleClass instead. It will be removed in or after version 1.0'
|
33
|
+
)
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'allows backward-compatible class to be subclassed' do
|
38
|
+
expect {
|
39
|
+
with_warn_squelching { Class.new(SampleDeprecatedClass) }
|
40
|
+
}.not_to raise_error
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'allows rescuing of a current error with a deprecated error' do
|
44
|
+
expect { raise SampleClass, nil }.to raise_error(SampleDeprecatedClass)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'allows rescuing of a current error with a current error' do
|
48
|
+
expect { raise SampleClass, nil }.to raise_error(SampleClass)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'allows rescuing of a deprecated error with a deprecated error' do
|
52
|
+
expect { raise SampleDeprecatedClass, nil }.to raise_error(SampleDeprecatedClass)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'allows rescuing of a deprecated error with a current error' do
|
56
|
+
expect { raise SampleDeprecatedClass, nil }.to raise_error(SampleClass)
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'match behavior' do
|
60
|
+
class SampleDeprecatedClassA < SampleDeprecatedClass; end
|
61
|
+
class SampleDeprecatedClassB < SampleDeprecatedClass; end
|
62
|
+
|
63
|
+
class SampleDeprecatedClassAX < SampleDeprecatedClassA; end
|
64
|
+
|
65
|
+
class SampleClassA < SampleClass; end
|
66
|
+
|
67
|
+
describe 'undeprecated class' do
|
68
|
+
it 'is === to instance of deprecated class' do
|
69
|
+
expect(SampleClass === SampleDeprecatedClass.new).to be true
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'is === to instance of subclass of deprecated class' do
|
73
|
+
expect(SampleClass === SampleDeprecatedClassA.new).to be true
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'is === to instance of subclass of subclass of deprecated class' do
|
77
|
+
expect(SampleClass === SampleDeprecatedClassAX.new).to be true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe 'subclass of undeprecated class' do
|
82
|
+
it 'is not === to instance of undeprecated class' do
|
83
|
+
expect(SampleClassA === SampleClass.new).to be false
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'is not === to instance of deprecated class' do
|
87
|
+
expect(SampleClassA === SampleDeprecatedClass.new).to be false
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe 'deprecated class' do
|
92
|
+
it 'is === to instance of undeprecated class' do
|
93
|
+
expect(SampleDeprecatedClass === SampleClass.new).to be true
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'is === to instance of subclass of undeprecated class' do
|
97
|
+
expect(SampleDeprecatedClass === SampleClassA.new).to be true
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'is === to instance of subclass of deprecated class' do
|
101
|
+
expect(SampleDeprecatedClass === SampleDeprecatedClassA.new).to be true
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'is === to instance of subclass of subclass of deprecated class' do
|
105
|
+
expect(SampleDeprecatedClass === SampleDeprecatedClassAX.new).to be true
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe 'subclass of deprecated class' do
|
110
|
+
it 'is not === to instance of subclass of undeprecated class' do
|
111
|
+
expect(SampleDeprecatedClassA === SampleClass.new).to be false
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'is not === to instance of another subclass of deprecated class' do
|
115
|
+
expect(SampleDeprecatedClassA === SampleDeprecatedClassB.new).to be false
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'is === to instance of its subclass' do
|
119
|
+
expect(SampleDeprecatedClassA === SampleDeprecatedClassAX.new).to be true
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'is === to instance of deprecated class' do
|
123
|
+
expect(SampleDeprecatedClass === SampleDeprecatedClassB.new).to be true
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe 'subclass of subclass of deprecated class' do
|
128
|
+
it 'is not === to instance of subclass of another subclass of deprecated class' do
|
129
|
+
expect(SampleDeprecatedClassAX === SampleDeprecatedClassB.new).to be false
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'is not === to instance of its superclass' do
|
133
|
+
expect(SampleDeprecatedClassA === SampleDeprecatedClass.new).to be false
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def with_warn_squelching
|
139
|
+
stderr_catcher = StringIO.new
|
140
|
+
original_stderr = $stderr
|
141
|
+
$stderr = stderr_catcher
|
142
|
+
result = yield if block_given?
|
143
|
+
[stderr_catcher.tap(&:rewind).string, result]
|
144
|
+
ensure
|
145
|
+
$stderr = original_stderr
|
146
|
+
end
|
147
|
+
end
|