faraday 0.16.0 → 0.17.4
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/CHANGELOG.md +232 -0
- data/LICENSE.md +1 -1
- data/README.md +358 -18
- data/Rakefile +13 -0
- data/lib/faraday/adapter/em_http.rb +97 -140
- data/lib/faraday/adapter/em_http_ssl_patch.rb +17 -23
- data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +15 -18
- data/lib/faraday/adapter/em_synchrony.rb +60 -104
- data/lib/faraday/adapter/excon.rb +55 -100
- data/lib/faraday/adapter/httpclient.rb +39 -61
- data/lib/faraday/adapter/net_http.rb +51 -103
- data/lib/faraday/adapter/net_http_persistent.rb +28 -49
- 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/adapter.rb +22 -36
- data/lib/faraday/autoload.rb +36 -47
- data/lib/faraday/connection.rb +179 -321
- data/lib/faraday/deprecate.rb +109 -0
- data/lib/faraday/error.rb +79 -21
- data/lib/faraday/middleware.rb +28 -4
- data/lib/faraday/options.rb +183 -32
- data/lib/faraday/parameters.rb +197 -4
- data/lib/faraday/rack_builder.rb +55 -66
- 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 +171 -197
- data/lib/faraday/request/token_authentication.rb +10 -15
- data/lib/faraday/request/url_encoded.rb +23 -41
- data/lib/faraday/request.rb +36 -68
- data/lib/faraday/response/logger.rb +69 -22
- data/lib/faraday/response/raise_error.rb +18 -36
- data/lib/faraday/response.rb +13 -20
- data/lib/faraday/upload_io.rb +67 -0
- data/lib/faraday/utils.rb +245 -28
- data/lib/faraday.rb +174 -93
- 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/default_test.rb +14 -0
- data/test/adapters/em_http_test.rb +30 -0
- data/test/adapters/em_synchrony_test.rb +32 -0
- data/test/adapters/excon_test.rb +30 -0
- data/test/adapters/httpclient_test.rb +34 -0
- data/test/adapters/integration.rb +263 -0
- data/test/adapters/logger_test.rb +136 -0
- data/test/adapters/net_http_persistent_test.rb +114 -0
- data/test/adapters/net_http_test.rb +79 -0
- data/test/adapters/patron_test.rb +40 -0
- data/test/adapters/rack_test.rb +38 -0
- data/test/adapters/test_middleware_test.rb +157 -0
- data/test/adapters/typhoeus_test.rb +38 -0
- data/test/authentication_middleware_test.rb +65 -0
- data/test/composite_read_io_test.rb +109 -0
- data/test/connection_test.rb +738 -0
- data/test/env_test.rb +268 -0
- data/test/helper.rb +75 -0
- data/test/live_server.rb +67 -0
- data/test/middleware/instrumentation_test.rb +88 -0
- data/test/middleware/retry_test.rb +282 -0
- data/test/middleware_stack_test.rb +260 -0
- data/test/multibyte.txt +1 -0
- data/test/options_test.rb +333 -0
- data/test/parameters_test.rb +157 -0
- data/test/request_middleware_test.rb +126 -0
- data/test/response_middleware_test.rb +72 -0
- data/test/strawberry.rb +2 -0
- data/test/utils_test.rb +98 -0
- metadata +50 -25
- data/lib/faraday/adapter_registry.rb +0 -28
- data/lib/faraday/dependency_loader.rb +0 -37
- 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
@@ -1,97 +1,66 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require File.expand_path('url_encoded', __dir__)
|
1
|
+
require File.expand_path("../url_encoded", __FILE__)
|
4
2
|
require 'securerandom'
|
5
3
|
|
6
4
|
module Faraday
|
7
|
-
class Request
|
8
|
-
|
9
|
-
|
10
|
-
self.mime_type = 'multipart/form-data'
|
11
|
-
unless defined? DEFAULT_BOUNDARY_PREFIX
|
12
|
-
DEFAULT_BOUNDARY_PREFIX = '-----------RubyMultipartPost'
|
13
|
-
end
|
5
|
+
class Request::Multipart < Request::UrlEncoded
|
6
|
+
self.mime_type = 'multipart/form-data'.freeze
|
7
|
+
DEFAULT_BOUNDARY_PREFIX = "-----------RubyMultipartPost".freeze unless defined? DEFAULT_BOUNDARY_PREFIX
|
14
8
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
env.request.boundary ||= unique_boundary
|
21
|
-
env.request_headers[CONTENT_TYPE] +=
|
22
|
-
"; boundary=#{env.request.boundary}"
|
23
|
-
env.body = create_multipart(env, params)
|
24
|
-
end
|
25
|
-
@app.call env
|
9
|
+
def call(env)
|
10
|
+
match_content_type(env) do |params|
|
11
|
+
env.request.boundary ||= unique_boundary
|
12
|
+
env.request_headers[CONTENT_TYPE] += "; boundary=#{env.request.boundary}"
|
13
|
+
env.body = create_multipart(env, params)
|
26
14
|
end
|
15
|
+
@app.call env
|
16
|
+
end
|
27
17
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
18
|
+
def process_request?(env)
|
19
|
+
type = request_type(env)
|
20
|
+
env.body.respond_to?(:each_key) and !env.body.empty? and (
|
21
|
+
(type.empty? and has_multipart?(env.body)) or
|
22
|
+
type == self.class.mime_type
|
23
|
+
)
|
24
|
+
end
|
36
25
|
|
37
|
-
|
38
|
-
#
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
if obj.respond_to?(:each)
|
43
|
-
(obj.respond_to?(:values) ? obj.values : obj).each do |val|
|
44
|
-
return true if val.respond_to?(:content_type) || has_multipart?(val)
|
45
|
-
end
|
26
|
+
def has_multipart?(obj)
|
27
|
+
# string is an enum in 1.8, returning list of itself
|
28
|
+
if obj.respond_to?(:each) && !obj.is_a?(String)
|
29
|
+
(obj.respond_to?(:values) ? obj.values : obj).each do |val|
|
30
|
+
return true if (val.respond_to?(:content_type) || has_multipart?(val))
|
46
31
|
end
|
47
|
-
false
|
48
32
|
end
|
33
|
+
false
|
34
|
+
end
|
49
35
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
boundary
|
54
|
-
parts = process_params(params) do |key, value|
|
55
|
-
part(boundary, key, value)
|
56
|
-
end
|
57
|
-
parts << Faraday::Parts::EpiloguePart.new(boundary)
|
58
|
-
|
59
|
-
body = Faraday::CompositeReadIO.new(parts)
|
60
|
-
env.request_headers[Faraday::Env::ContentLength] = body.length.to_s
|
61
|
-
body
|
36
|
+
def create_multipart(env, params)
|
37
|
+
boundary = env.request.boundary
|
38
|
+
parts = process_params(params) do |key, value|
|
39
|
+
Faraday::Parts::Part.new(boundary, key, value)
|
62
40
|
end
|
41
|
+
parts << Faraday::Parts::EpiloguePart.new(boundary)
|
63
42
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
Faraday::Parts::Part.new(boundary, key, value)
|
69
|
-
end
|
70
|
-
end
|
43
|
+
body = Faraday::CompositeReadIO.new(parts)
|
44
|
+
env.request_headers[Faraday::Env::ContentLength] = body.length.to_s
|
45
|
+
return body
|
46
|
+
end
|
71
47
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
end
|
48
|
+
def unique_boundary
|
49
|
+
"#{DEFAULT_BOUNDARY_PREFIX}-#{SecureRandom.hex}"
|
50
|
+
end
|
76
51
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
def process_params(params, prefix = nil, pieces = nil, &block)
|
81
|
-
params.inject(pieces || []) do |all, (key, value)|
|
82
|
-
key = "#{prefix}[#{key}]" if prefix
|
52
|
+
def process_params(params, prefix = nil, pieces = nil, &block)
|
53
|
+
params.inject(pieces || []) do |all, (key, value)|
|
54
|
+
key = "#{prefix}[#{key}]" if prefix
|
83
55
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
all << block.call(key, value)
|
93
|
-
# rubocop:enable Performance/RedundantBlockCall
|
94
|
-
end
|
56
|
+
case value
|
57
|
+
when Array
|
58
|
+
values = value.inject([]) { |a,v| a << [nil, v] }
|
59
|
+
process_params(values, key, all, &block)
|
60
|
+
when Hash
|
61
|
+
process_params(value, key, all, &block)
|
62
|
+
else
|
63
|
+
all << block.call(key, value)
|
95
64
|
end
|
96
65
|
end
|
97
66
|
end
|
@@ -1,239 +1,213 @@
|
|
1
|
-
|
1
|
+
require 'date'
|
2
2
|
|
3
3
|
module Faraday
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
def self.from(value)
|
42
|
-
if value.is_a?(Integer)
|
43
|
-
new(value)
|
44
|
-
else
|
45
|
-
super(value)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def max
|
50
|
-
(self[:max] ||= 2).to_i
|
4
|
+
# Catches exceptions and retries each request a limited number of times.
|
5
|
+
#
|
6
|
+
# By default, it retries 2 times and handles only timeout exceptions. It can
|
7
|
+
# be configured with an arbitrary number of retries, a list of exceptions to
|
8
|
+
# handle, a retry interval, a percentage of randomness to add to the retry
|
9
|
+
# interval, and a backoff factor.
|
10
|
+
#
|
11
|
+
# Examples
|
12
|
+
#
|
13
|
+
# Faraday.new do |conn|
|
14
|
+
# conn.request :retry, max: 2, interval: 0.05,
|
15
|
+
# interval_randomness: 0.5, backoff_factor: 2,
|
16
|
+
# exceptions: [CustomException, 'Timeout::Error']
|
17
|
+
# conn.adapter ...
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# This example will result in a first interval that is random between 0.05 and 0.075 and a second
|
21
|
+
# interval that is random between 0.1 and 0.15
|
22
|
+
#
|
23
|
+
class Request::Retry < Faraday::Middleware
|
24
|
+
DEFAULT_EXCEPTIONS = [Errno::ETIMEDOUT, 'Timeout::Error',
|
25
|
+
Faraday::TimeoutError, Faraday::RetriableResponse
|
26
|
+
].freeze
|
27
|
+
IDEMPOTENT_METHODS = [:delete, :get, :head, :options, :put]
|
28
|
+
|
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
|
+
|
33
|
+
DEFAULT_CHECK = lambda { |env,exception| false }
|
34
|
+
|
35
|
+
def self.from(value)
|
36
|
+
if Integer === value
|
37
|
+
new(value)
|
38
|
+
else
|
39
|
+
super(value)
|
51
40
|
end
|
41
|
+
end
|
52
42
|
|
53
|
-
|
54
|
-
|
55
|
-
|
43
|
+
def max
|
44
|
+
(self[:max] ||= 2).to_i
|
45
|
+
end
|
56
46
|
|
57
|
-
|
58
|
-
|
59
|
-
|
47
|
+
def interval
|
48
|
+
(self[:interval] ||= 0).to_f
|
49
|
+
end
|
60
50
|
|
61
|
-
|
62
|
-
|
63
|
-
|
51
|
+
def max_interval
|
52
|
+
(self[:max_interval] ||= Float::MAX).to_f
|
53
|
+
end
|
64
54
|
|
65
|
-
|
66
|
-
|
67
|
-
|
55
|
+
def interval_randomness
|
56
|
+
(self[:interval_randomness] ||= 0).to_f
|
57
|
+
end
|
68
58
|
|
69
|
-
|
70
|
-
|
71
|
-
|
59
|
+
def backoff_factor
|
60
|
+
(self[:backoff_factor] ||= 1).to_f
|
61
|
+
end
|
72
62
|
|
73
|
-
|
74
|
-
|
75
|
-
|
63
|
+
def exceptions
|
64
|
+
Array(self[:exceptions] ||= DEFAULT_EXCEPTIONS)
|
65
|
+
end
|
76
66
|
|
77
|
-
|
78
|
-
|
79
|
-
|
67
|
+
def methods
|
68
|
+
Array(self[:methods] ||= IDEMPOTENT_METHODS)
|
69
|
+
end
|
80
70
|
|
81
|
-
|
82
|
-
|
83
|
-
|
71
|
+
def retry_if
|
72
|
+
self[:retry_if] ||= DEFAULT_CHECK
|
73
|
+
end
|
84
74
|
|
85
|
-
|
86
|
-
|
87
|
-
end
|
75
|
+
def retry_block
|
76
|
+
self[:retry_block] ||= Proc.new {}
|
88
77
|
end
|
89
78
|
|
90
|
-
|
91
|
-
|
92
|
-
# @option options [Integer] :max (2) Maximum number of retries
|
93
|
-
# @option options [Integer] :interval (0) Pause in seconds between retries
|
94
|
-
# @option options [Integer] :interval_randomness (0) The maximum random
|
95
|
-
# interval amount expressed as a float between
|
96
|
-
# 0 and 1 to use in addition to the interval.
|
97
|
-
# @option options [Integer] :max_interval (Float::MAX) An upper limit
|
98
|
-
# for the interval
|
99
|
-
# @option options [Integer] :backoff_factor (1) The amount to multiply
|
100
|
-
# each successive retry's interval amount by in order to provide backoff
|
101
|
-
# @option options [Array] :exceptions ([ Errno::ETIMEDOUT,
|
102
|
-
# 'Timeout::Error', Faraday::TimeoutError, Faraday::RetriableResponse])
|
103
|
-
# The list of exceptions to handle. Exceptions can be given as
|
104
|
-
# Class, Module, or String.
|
105
|
-
# @option options [Array] :methods (the idempotent HTTP methods
|
106
|
-
# in IDEMPOTENT_METHODS) A list of HTTP methods to retry without
|
107
|
-
# calling retry_if. Pass an empty Array to call retry_if
|
108
|
-
# for all exceptions.
|
109
|
-
# @option options [Block] :retry_if (false) block that will receive
|
110
|
-
# the env object and the exception raised
|
111
|
-
# and should decide if the code should retry still the action or
|
112
|
-
# not independent of the retry count. This would be useful
|
113
|
-
# if the exception produced is non-recoverable or if the
|
114
|
-
# the HTTP method called is not idempotent.
|
115
|
-
# @option options [Block] :retry_block block that is executed after
|
116
|
-
# every retry. Request environment, middleware options, current number
|
117
|
-
# of retries and the exception is passed to the block as parameters.
|
118
|
-
# @option options [Array] :retry_statuses Array of Integer HTTP status
|
119
|
-
# codes or a single Integer value that determines whether to raise
|
120
|
-
# a Faraday::RetriableResponse exception based on the HTTP status code
|
121
|
-
# of an HTTP response.
|
122
|
-
def initialize(app, options = nil)
|
123
|
-
super(app)
|
124
|
-
@options = Options.from(options)
|
125
|
-
@errmatch = build_exception_matcher(@options.exceptions)
|
79
|
+
def retry_statuses
|
80
|
+
Array(self[:retry_statuses] ||= [])
|
126
81
|
end
|
82
|
+
end
|
127
83
|
|
128
|
-
|
129
|
-
|
130
|
-
|
84
|
+
# Public: Initialize middleware
|
85
|
+
#
|
86
|
+
# Options:
|
87
|
+
# max - Maximum number of retries (default: 2)
|
88
|
+
# interval - Pause in seconds between retries (default: 0)
|
89
|
+
# interval_randomness - The maximum random interval amount expressed
|
90
|
+
# as a float between 0 and 1 to use in addition to the
|
91
|
+
# interval. (default: 0)
|
92
|
+
# max_interval - An upper limit for the interval (default: Float::MAX)
|
93
|
+
# backoff_factor - The amount to multiple each successive retry's
|
94
|
+
# interval amount by in order to provide backoff
|
95
|
+
# (default: 1)
|
96
|
+
# exceptions - The list of exceptions to handle. Exceptions can be
|
97
|
+
# given as Class, Module, or String. (default:
|
98
|
+
# [Errno::ETIMEDOUT, 'Timeout::Error',
|
99
|
+
# Faraday::TimeoutError, Faraday::RetriableResponse])
|
100
|
+
# methods - A list of HTTP methods to retry without calling retry_if. Pass
|
101
|
+
# an empty Array to call retry_if for all exceptions.
|
102
|
+
# (defaults to the idempotent HTTP methods in IDEMPOTENT_METHODS)
|
103
|
+
# retry_if - block that will receive the env object and the exception raised
|
104
|
+
# and should decide if the code should retry still the action or
|
105
|
+
# not independent of the retry count. This would be useful
|
106
|
+
# if the exception produced is non-recoverable or if the
|
107
|
+
# the HTTP method called is not idempotent.
|
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.
|
111
|
+
def initialize(app, options = nil)
|
112
|
+
super(app)
|
113
|
+
@options = Options.from(options)
|
114
|
+
@errmatch = build_exception_matcher(@options.exceptions)
|
115
|
+
end
|
131
116
|
|
132
|
-
|
117
|
+
def calculate_sleep_amount(retries, env)
|
118
|
+
retry_after = calculate_retry_after(env)
|
119
|
+
retry_interval = calculate_retry_interval(retries)
|
133
120
|
|
134
|
-
|
135
|
-
retry_after
|
136
|
-
else
|
137
|
-
retry_interval
|
138
|
-
end
|
139
|
-
end
|
121
|
+
return if retry_after && retry_after > @options.max_interval
|
140
122
|
|
141
|
-
|
142
|
-
|
143
|
-
retries = @options.max
|
144
|
-
request_body = env[:body]
|
145
|
-
begin
|
146
|
-
# after failure env[:body] is set to the response body
|
147
|
-
env[:body] = request_body
|
148
|
-
@app.call(env).tap do |resp|
|
149
|
-
if @options.retry_statuses.include?(resp.status)
|
150
|
-
raise Faraday::RetriableResponse.new(nil, resp)
|
151
|
-
end
|
152
|
-
end
|
153
|
-
rescue @errmatch => e
|
154
|
-
if retries.positive? && retry_request?(env, e)
|
155
|
-
retries -= 1
|
156
|
-
rewind_files(request_body)
|
157
|
-
@options.retry_block.call(env, @options, retries, e)
|
158
|
-
if (sleep_amount = calculate_sleep_amount(retries + 1, env))
|
159
|
-
sleep sleep_amount
|
160
|
-
retry
|
161
|
-
end
|
162
|
-
end
|
123
|
+
retry_after && retry_after >= retry_interval ? retry_after : retry_interval
|
124
|
+
end
|
163
125
|
|
164
|
-
|
126
|
+
def call(env)
|
127
|
+
retries = @options.max
|
128
|
+
request_body = env[:body]
|
129
|
+
begin
|
130
|
+
env[:body] = request_body # after failure env[:body] is set to the response body
|
131
|
+
@app.call(env).tap do |resp|
|
132
|
+
raise Faraday::RetriableResponse.new(nil, resp) if @options.retry_statuses.include?(resp.status)
|
133
|
+
end
|
134
|
+
rescue @errmatch => exception
|
135
|
+
if retries > 0 && retry_request?(env, exception)
|
136
|
+
retries -= 1
|
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
|
165
144
|
|
166
|
-
|
145
|
+
if exception.is_a?(Faraday::RetriableResponse)
|
146
|
+
exception.response
|
147
|
+
else
|
148
|
+
raise
|
167
149
|
end
|
168
150
|
end
|
151
|
+
end
|
169
152
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
exceptions.any? do |ex|
|
184
|
-
if ex.is_a? Module
|
185
|
-
error.is_a? ex
|
186
|
-
else
|
187
|
-
error.class.to_s == ex.to_s
|
188
|
-
end
|
153
|
+
# Private: construct an exception matcher object.
|
154
|
+
#
|
155
|
+
# An exception matcher for the rescue clause can usually be any object that
|
156
|
+
# responds to `===`, but for Ruby 1.8 it has to be a Class or Module.
|
157
|
+
def build_exception_matcher(exceptions)
|
158
|
+
matcher = Module.new
|
159
|
+
(class << matcher; self; end).class_eval do
|
160
|
+
define_method(:===) do |error|
|
161
|
+
exceptions.any? do |ex|
|
162
|
+
if ex.is_a? Module
|
163
|
+
error.is_a? ex
|
164
|
+
else
|
165
|
+
error.class.to_s == ex.to_s
|
189
166
|
end
|
190
167
|
end
|
191
168
|
end
|
192
|
-
matcher
|
193
169
|
end
|
170
|
+
matcher
|
171
|
+
end
|
194
172
|
|
195
|
-
|
196
|
-
|
197
|
-
def retry_request?(env, exception)
|
198
|
-
@options.methods.include?(env[:method]) ||
|
199
|
-
@options.retry_if.call(env, exception)
|
200
|
-
end
|
173
|
+
private
|
201
174
|
|
202
|
-
|
203
|
-
|
175
|
+
def retry_request?(env, exception)
|
176
|
+
@options.methods.include?(env[:method]) || @options.retry_if.call(env, exception)
|
177
|
+
end
|
204
178
|
|
205
|
-
|
206
|
-
|
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
|
207
184
|
end
|
208
185
|
end
|
186
|
+
end
|
209
187
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
return unless response_headers
|
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
|
215
192
|
|
216
|
-
|
193
|
+
retry_after_value = env[:response_headers]["Retry-After"]
|
217
194
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
end
|
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
|
225
201
|
end
|
202
|
+
end
|
226
203
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
random_interval = rand * @options.interval_randomness.to_f *
|
233
|
-
@options.interval
|
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
|
234
209
|
|
235
|
-
|
236
|
-
end
|
210
|
+
current_interval + random_interval
|
237
211
|
end
|
238
212
|
end
|
239
213
|
end
|
@@ -1,20 +1,15 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
module Faraday
|
4
|
-
class Request
|
5
|
-
#
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
options[:token] = token
|
12
|
-
super(:Token, options)
|
13
|
-
end
|
2
|
+
class Request::TokenAuthentication < Request.load_middleware(:authorization)
|
3
|
+
# Public
|
4
|
+
def self.header(token, options = nil)
|
5
|
+
options ||= {}
|
6
|
+
options[:token] = token
|
7
|
+
super(:Token, options)
|
8
|
+
end
|
14
9
|
|
15
|
-
|
16
|
-
|
17
|
-
end
|
10
|
+
def initialize(app, token, options = nil)
|
11
|
+
super(app, token, options)
|
18
12
|
end
|
19
13
|
end
|
20
14
|
end
|
15
|
+
|