faraday 0.11.0 → 1.4.3
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 +5 -5
- data/CHANGELOG.md +380 -0
- data/LICENSE.md +1 -1
- data/README.md +25 -229
- data/Rakefile +7 -0
- data/examples/client_spec.rb +65 -0
- data/examples/client_test.rb +79 -0
- data/lib/faraday/adapter/httpclient.rb +83 -59
- data/lib/faraday/adapter/patron.rb +92 -36
- data/lib/faraday/adapter/rack.rb +30 -13
- data/lib/faraday/adapter/test.rb +103 -62
- data/lib/faraday/adapter/typhoeus.rb +7 -115
- data/lib/faraday/adapter.rb +77 -22
- data/lib/faraday/adapter_registry.rb +30 -0
- data/lib/faraday/autoload.rb +42 -36
- data/lib/faraday/connection.rb +351 -167
- data/lib/faraday/dependency_loader.rb +37 -0
- data/lib/faraday/encoders/flat_params_encoder.rb +105 -0
- data/lib/faraday/encoders/nested_params_encoder.rb +176 -0
- data/lib/faraday/error.rb +127 -38
- data/lib/faraday/file_part.rb +128 -0
- data/lib/faraday/logging/formatter.rb +105 -0
- data/lib/faraday/methods.rb +6 -0
- data/lib/faraday/middleware.rb +19 -25
- 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 +32 -0
- data/lib/faraday/options/request_options.rb +22 -0
- data/lib/faraday/options/ssl_options.rb +59 -0
- data/lib/faraday/options.rb +58 -207
- data/lib/faraday/param_part.rb +53 -0
- data/lib/faraday/parameters.rb +4 -196
- data/lib/faraday/rack_builder.rb +84 -48
- data/lib/faraday/request/authorization.rb +44 -30
- data/lib/faraday/request/basic_authentication.rb +14 -7
- data/lib/faraday/request/instrumentation.rb +45 -27
- data/lib/faraday/request/multipart.rb +88 -45
- data/lib/faraday/request/retry.rb +211 -126
- data/lib/faraday/request/token_authentication.rb +15 -10
- data/lib/faraday/request/url_encoded.rb +43 -23
- data/lib/faraday/request.rb +94 -32
- data/lib/faraday/response/logger.rb +22 -69
- data/lib/faraday/response/raise_error.rb +49 -14
- data/lib/faraday/response.rb +27 -23
- data/lib/faraday/utils/headers.rb +139 -0
- data/lib/faraday/utils/params_hash.rb +61 -0
- data/lib/faraday/utils.rb +38 -238
- data/lib/faraday/version.rb +5 -0
- data/lib/faraday.rb +124 -187
- 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_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/test_spec.rb +260 -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 +736 -0
- data/spec/faraday/error_spec.rb +60 -0
- data/spec/faraday/middleware_spec.rb +52 -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 +44 -0
- data/spec/faraday/options/request_options_spec.rb +19 -0
- data/spec/faraday/params_encoders/flat_spec.rb +42 -0
- data/spec/faraday/params_encoders/nested_spec.rb +142 -0
- data/spec/faraday/rack_builder_spec.rb +345 -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 +302 -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 +120 -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 +169 -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 +105 -0
- data/spec/support/shared_examples/params_encoder.rb +18 -0
- data/spec/support/shared_examples/request_method.rb +262 -0
- data/spec/support/streaming_response_checker.rb +35 -0
- data/spec/support/webmock_rack_app.rb +68 -0
- metadata +164 -16
- data/lib/faraday/adapter/em_http.rb +0 -243
- data/lib/faraday/adapter/em_http_ssl_patch.rb +0 -56
- data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +0 -66
- data/lib/faraday/adapter/em_synchrony.rb +0 -106
- data/lib/faraday/adapter/excon.rb +0 -80
- data/lib/faraday/adapter/net_http.rb +0 -135
- data/lib/faraday/adapter/net_http_persistent.rb +0 -50
- data/lib/faraday/upload_io.rb +0 -67
@@ -1,154 +1,239 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Faraday
|
2
|
-
|
3
|
-
|
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
|
-
|
4
|
+
class Request
|
5
|
+
# Catches exceptions and retries each request a limited number of times.
|
6
|
+
#
|
7
|
+
# By default, it retries 2 times and handles only timeout exceptions. It can
|
8
|
+
# be configured with an arbitrary number of retries, a list of exceptions to
|
9
|
+
# handle, a retry interval, a percentage of randomness to add to the retry
|
10
|
+
# interval, and a backoff factor.
|
11
|
+
#
|
12
|
+
# @example Configure Retry middleware using intervals
|
13
|
+
# Faraday.new do |conn|
|
14
|
+
# conn.request(:retry, max: 2,
|
15
|
+
# interval: 0.05,
|
16
|
+
# interval_randomness: 0.5,
|
17
|
+
# backoff_factor: 2,
|
18
|
+
# exceptions: [CustomException, 'Timeout::Error'])
|
19
|
+
#
|
20
|
+
# conn.adapter(:net_http) # NB: Last middleware must be the adapter
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# This example will result in a first interval that is random between 0.05
|
24
|
+
# and 0.075 and a second interval that is random between 0.1 and 0.125.
|
25
|
+
class Retry < Faraday::Middleware
|
26
|
+
DEFAULT_EXCEPTIONS = [
|
27
|
+
Errno::ETIMEDOUT, 'Timeout::Error',
|
28
|
+
Faraday::TimeoutError, Faraday::RetriableResponse
|
29
|
+
].freeze
|
30
|
+
IDEMPOTENT_METHODS = %i[delete get head options put].freeze
|
31
|
+
|
32
|
+
# Options contains the configurable parameters for the Retry middleware.
|
33
|
+
class Options < Faraday::Options.new(:max, :interval, :max_interval,
|
34
|
+
:interval_randomness,
|
35
|
+
:backoff_factor, :exceptions,
|
36
|
+
:methods, :retry_if, :retry_block,
|
37
|
+
:retry_statuses)
|
38
|
+
|
39
|
+
DEFAULT_CHECK = ->(_env, _exception) { false }
|
40
|
+
|
41
|
+
def self.from(value)
|
42
|
+
if value.is_a?(Integer)
|
43
|
+
new(value)
|
44
|
+
else
|
45
|
+
super(value)
|
46
|
+
end
|
34
47
|
end
|
35
|
-
end
|
36
48
|
|
37
|
-
|
38
|
-
|
39
|
-
|
49
|
+
def max
|
50
|
+
(self[:max] ||= 2).to_i
|
51
|
+
end
|
40
52
|
|
41
|
-
|
42
|
-
|
43
|
-
|
53
|
+
def interval
|
54
|
+
(self[:interval] ||= 0).to_f
|
55
|
+
end
|
44
56
|
|
45
|
-
|
46
|
-
|
47
|
-
|
57
|
+
def max_interval
|
58
|
+
(self[:max_interval] ||= Float::MAX).to_f
|
59
|
+
end
|
48
60
|
|
49
|
-
|
50
|
-
|
61
|
+
def interval_randomness
|
62
|
+
(self[:interval_randomness] ||= 0).to_f
|
63
|
+
end
|
64
|
+
|
65
|
+
def backoff_factor
|
66
|
+
(self[:backoff_factor] ||= 1).to_f
|
67
|
+
end
|
68
|
+
|
69
|
+
def exceptions
|
70
|
+
Array(self[:exceptions] ||= DEFAULT_EXCEPTIONS)
|
71
|
+
end
|
72
|
+
|
73
|
+
def methods
|
74
|
+
Array(self[:methods] ||= IDEMPOTENT_METHODS)
|
75
|
+
end
|
76
|
+
|
77
|
+
def retry_if
|
78
|
+
self[:retry_if] ||= DEFAULT_CHECK
|
79
|
+
end
|
80
|
+
|
81
|
+
def retry_block
|
82
|
+
self[:retry_block] ||= proc {}
|
83
|
+
end
|
84
|
+
|
85
|
+
def retry_statuses
|
86
|
+
Array(self[:retry_statuses] ||= [])
|
87
|
+
end
|
51
88
|
end
|
52
89
|
|
53
|
-
|
54
|
-
|
90
|
+
# @param app [#call]
|
91
|
+
# @param options [Hash]
|
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 before
|
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)
|
55
126
|
end
|
56
127
|
|
57
|
-
def
|
58
|
-
|
59
|
-
|
128
|
+
def calculate_sleep_amount(retries, env)
|
129
|
+
retry_after = calculate_retry_after(env)
|
130
|
+
retry_interval = calculate_retry_interval(retries)
|
131
|
+
|
132
|
+
return if retry_after && retry_after > @options.max_interval
|
133
|
+
|
134
|
+
if retry_after && retry_after >= retry_interval
|
135
|
+
retry_after
|
136
|
+
else
|
137
|
+
retry_interval
|
138
|
+
end
|
60
139
|
end
|
61
140
|
|
62
|
-
|
63
|
-
|
141
|
+
# @param env [Faraday::Env]
|
142
|
+
def call(env)
|
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
|
163
|
+
|
164
|
+
raise unless e.is_a?(Faraday::RetriableResponse)
|
165
|
+
|
166
|
+
e.response
|
167
|
+
end
|
64
168
|
end
|
65
169
|
|
66
|
-
|
67
|
-
|
170
|
+
# An exception matcher for the rescue clause can usually be any object
|
171
|
+
# that responds to `===`, but for Ruby 1.8 it has to be a Class or Module.
|
172
|
+
#
|
173
|
+
# @param exceptions [Array]
|
174
|
+
# @api private
|
175
|
+
# @return [Module] an exception matcher
|
176
|
+
def build_exception_matcher(exceptions)
|
177
|
+
matcher = Module.new
|
178
|
+
(
|
179
|
+
class << matcher
|
180
|
+
self
|
181
|
+
end).class_eval do
|
182
|
+
define_method(:===) do |error|
|
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
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
matcher
|
68
193
|
end
|
69
194
|
|
70
|
-
|
195
|
+
private
|
71
196
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
# interval - Pause in seconds between retries (default: 0)
|
77
|
-
# interval_randomness - The maximum random interval amount expressed
|
78
|
-
# as a float between 0 and 1 to use in addition to the
|
79
|
-
# interval. (default: 0)
|
80
|
-
# max_interval - An upper limit for the interval (default: Float::MAX)
|
81
|
-
# backoff_factor - The amount to multiple each successive retry's
|
82
|
-
# interval amount by in order to provide backoff
|
83
|
-
# (default: 1)
|
84
|
-
# exceptions - The list of exceptions to handle. Exceptions can be
|
85
|
-
# given as Class, Module, or String. (default:
|
86
|
-
# [Errno::ETIMEDOUT, Timeout::Error,
|
87
|
-
# Error::TimeoutError])
|
88
|
-
# methods - A list of HTTP methods to retry without calling retry_if. Pass
|
89
|
-
# an empty Array to call retry_if for all exceptions.
|
90
|
-
# (defaults to the idempotent HTTP methods in IDEMPOTENT_METHODS)
|
91
|
-
# retry_if - block that will receive the env object and the exception raised
|
92
|
-
# and should decide if the code should retry still the action or
|
93
|
-
# not independent of the retry count. This would be useful
|
94
|
-
# if the exception produced is non-recoverable or if the
|
95
|
-
# the HTTP method called is not idempotent.
|
96
|
-
# (defaults to return false)
|
97
|
-
def initialize(app, options = nil)
|
98
|
-
super(app)
|
99
|
-
@options = Options.from(options)
|
100
|
-
@errmatch = build_exception_matcher(@options.exceptions)
|
101
|
-
end
|
197
|
+
def retry_request?(env, exception)
|
198
|
+
@options.methods.include?(env[:method]) ||
|
199
|
+
@options.retry_if.call(env, exception)
|
200
|
+
end
|
102
201
|
|
103
|
-
|
104
|
-
|
105
|
-
current_interval = @options.interval * (@options.backoff_factor ** retry_index)
|
106
|
-
current_interval = [current_interval, @options.max_interval].min
|
107
|
-
random_interval = rand * @options.interval_randomness.to_f * @options.interval
|
108
|
-
current_interval + random_interval
|
109
|
-
end
|
202
|
+
def rewind_files(body)
|
203
|
+
return unless body.is_a?(Hash)
|
110
204
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
begin
|
115
|
-
env[:body] = request_body # after failure env[:body] is set to the response body
|
116
|
-
@app.call(env)
|
117
|
-
rescue @errmatch => exception
|
118
|
-
if retries > 0 && retry_request?(env, exception)
|
119
|
-
retries -= 1
|
120
|
-
sleep sleep_amount(retries + 1)
|
121
|
-
retry
|
122
|
-
end
|
123
|
-
raise
|
205
|
+
body.each do |_, value|
|
206
|
+
value.rewind if value.is_a?(UploadIO)
|
207
|
+
end
|
124
208
|
end
|
125
|
-
end
|
126
209
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
end
|
210
|
+
# MDN spec for Retry-After header:
|
211
|
+
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
|
212
|
+
def calculate_retry_after(env)
|
213
|
+
response_headers = env[:response_headers]
|
214
|
+
return unless response_headers
|
215
|
+
|
216
|
+
retry_after_value = env[:response_headers]['Retry-After']
|
217
|
+
|
218
|
+
# Try to parse date from the header value
|
219
|
+
begin
|
220
|
+
datetime = DateTime.rfc2822(retry_after_value)
|
221
|
+
datetime.to_time - Time.now.utc
|
222
|
+
rescue ArgumentError
|
223
|
+
retry_after_value.to_f
|
142
224
|
end
|
143
225
|
end
|
144
|
-
matcher
|
145
|
-
end
|
146
226
|
|
147
|
-
|
227
|
+
def calculate_retry_interval(retries)
|
228
|
+
retry_index = @options.max - retries
|
229
|
+
current_interval = @options.interval *
|
230
|
+
(@options.backoff_factor**retry_index)
|
231
|
+
current_interval = [current_interval, @options.max_interval].min
|
232
|
+
random_interval = rand * @options.interval_randomness.to_f *
|
233
|
+
@options.interval
|
148
234
|
|
149
|
-
|
150
|
-
|
235
|
+
current_interval + random_interval
|
236
|
+
end
|
151
237
|
end
|
152
|
-
|
153
238
|
end
|
154
239
|
end
|
@@ -1,15 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Faraday
|
2
|
-
class Request
|
3
|
-
#
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
class Request
|
5
|
+
# TokenAuthentication is a middleware that adds a 'Token' header to a
|
6
|
+
# Faraday request.
|
7
|
+
class TokenAuthentication < load_middleware(:authorization)
|
8
|
+
# Public
|
9
|
+
def self.header(token, options = nil)
|
10
|
+
options ||= {}
|
11
|
+
options[:token] = token
|
12
|
+
super(:Token, options)
|
13
|
+
end
|
9
14
|
|
10
|
-
|
11
|
-
|
15
|
+
def initialize(app, token, options = nil)
|
16
|
+
super(app, token, options)
|
17
|
+
end
|
12
18
|
end
|
13
19
|
end
|
14
20
|
end
|
15
|
-
|
@@ -1,36 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Faraday
|
2
|
-
class Request
|
3
|
-
|
4
|
+
class Request
|
5
|
+
# Middleware for supporting urlencoded requests.
|
6
|
+
class UrlEncoded < Faraday::Middleware
|
7
|
+
unless defined?(::Faraday::Request::UrlEncoded::CONTENT_TYPE)
|
8
|
+
CONTENT_TYPE = 'Content-Type'
|
9
|
+
end
|
4
10
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
11
|
+
class << self
|
12
|
+
attr_accessor :mime_type
|
13
|
+
end
|
14
|
+
self.mime_type = 'application/x-www-form-urlencoded'
|
9
15
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
16
|
+
# Encodes as "application/x-www-form-urlencoded" if not already encoded or
|
17
|
+
# of another type.
|
18
|
+
#
|
19
|
+
# @param env [Faraday::Env]
|
20
|
+
def call(env)
|
21
|
+
match_content_type(env) do |data|
|
22
|
+
params = Faraday::Utils::ParamsHash[data]
|
23
|
+
env.body = params.to_query(env.params_encoder)
|
24
|
+
end
|
25
|
+
@app.call env
|
14
26
|
end
|
15
|
-
@app.call env
|
16
|
-
end
|
17
27
|
|
18
|
-
|
19
|
-
|
28
|
+
# @param env [Faraday::Env]
|
29
|
+
# @yield [request_body] Body of the request
|
30
|
+
def match_content_type(env)
|
31
|
+
return unless process_request?(env)
|
32
|
+
|
20
33
|
env.request_headers[CONTENT_TYPE] ||= self.class.mime_type
|
21
34
|
yield(env.body) unless env.body.respond_to?(:to_str)
|
22
35
|
end
|
23
|
-
end
|
24
36
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
37
|
+
# @param env [Faraday::Env]
|
38
|
+
#
|
39
|
+
# @return [Boolean] True if the request has a body and its Content-Type is
|
40
|
+
# urlencoded.
|
41
|
+
def process_request?(env)
|
42
|
+
type = request_type(env)
|
43
|
+
env.body && (type.empty? || (type == self.class.mime_type))
|
44
|
+
end
|
29
45
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
46
|
+
# @param env [Faraday::Env]
|
47
|
+
#
|
48
|
+
# @return [String]
|
49
|
+
def request_type(env)
|
50
|
+
type = env.request_headers[CONTENT_TYPE].to_s
|
51
|
+
type = type.split(';', 2).first if type.index(';')
|
52
|
+
type
|
53
|
+
end
|
34
54
|
end
|
35
55
|
end
|
36
56
|
end
|
data/lib/faraday/request.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Faraday
|
2
|
-
# Used to setup
|
4
|
+
# Used to setup URLs, params, headers, and the request body in a sane manner.
|
3
5
|
#
|
6
|
+
# @example
|
4
7
|
# @connection.post do |req|
|
5
8
|
# req.url 'http://localhost', 'a' => '1' # 'http://localhost?a=1'
|
6
9
|
# req.headers['b'] = '2' # Header
|
@@ -9,25 +12,63 @@ module Faraday
|
|
9
12
|
# req.body = 'abc'
|
10
13
|
# end
|
11
14
|
#
|
12
|
-
|
15
|
+
# @!attribute http_method
|
16
|
+
# @return [Symbol] the HTTP method of the Request
|
17
|
+
# @!attribute path
|
18
|
+
# @return [URI, String] the path
|
19
|
+
# @!attribute params
|
20
|
+
# @return [Hash] query parameters
|
21
|
+
# @!attribute headers
|
22
|
+
# @return [Faraday::Utils::Headers] headers
|
23
|
+
# @!attribute body
|
24
|
+
# @return [Hash] body
|
25
|
+
# @!attribute options
|
26
|
+
# @return [RequestOptions] options
|
27
|
+
#
|
28
|
+
# rubocop:disable Style/StructInheritance
|
29
|
+
class Request < Struct.new(
|
30
|
+
:http_method, :path, :params, :headers, :body, :options
|
31
|
+
)
|
32
|
+
# rubocop:enable Style/StructInheritance
|
33
|
+
|
13
34
|
extend MiddlewareRegistry
|
14
35
|
|
15
|
-
register_middleware File.expand_path('
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
36
|
+
register_middleware File.expand_path('request', __dir__),
|
37
|
+
url_encoded: [:UrlEncoded, 'url_encoded'],
|
38
|
+
multipart: [:Multipart, 'multipart'],
|
39
|
+
retry: [:Retry, 'retry'],
|
40
|
+
authorization: [:Authorization, 'authorization'],
|
41
|
+
basic_auth: [
|
42
|
+
:BasicAuthentication,
|
43
|
+
'basic_authentication'
|
44
|
+
],
|
45
|
+
token_auth: [
|
46
|
+
:TokenAuthentication,
|
47
|
+
'token_authentication'
|
48
|
+
],
|
49
|
+
instrumentation: [:Instrumentation, 'instrumentation']
|
23
50
|
|
51
|
+
# @param request_method [String]
|
52
|
+
# @yield [request] for block customization, if block given
|
53
|
+
# @yieldparam request [Request]
|
54
|
+
# @return [Request]
|
24
55
|
def self.create(request_method)
|
25
56
|
new(request_method).tap do |request|
|
26
57
|
yield(request) if block_given?
|
27
58
|
end
|
28
59
|
end
|
29
60
|
|
30
|
-
|
61
|
+
def method
|
62
|
+
warn <<~TEXT
|
63
|
+
WARNING: `Faraday::Request##{__method__}` is deprecated; use `#http_method` instead. It will be removed in or after version 2.0.
|
64
|
+
`Faraday::Request##{__method__}` called from #{caller_locations(1..1).first}
|
65
|
+
TEXT
|
66
|
+
http_method
|
67
|
+
end
|
68
|
+
|
69
|
+
# Replace params, preserving the existing hash type.
|
70
|
+
#
|
71
|
+
# @param hash [Hash] new params
|
31
72
|
def params=(hash)
|
32
73
|
if params
|
33
74
|
params.replace hash
|
@@ -36,7 +77,9 @@ module Faraday
|
|
36
77
|
end
|
37
78
|
end
|
38
79
|
|
39
|
-
#
|
80
|
+
# Replace request headers, preserving the existing hash type.
|
81
|
+
#
|
82
|
+
# @param hash [Hash] new headers
|
40
83
|
def headers=(hash)
|
41
84
|
if headers
|
42
85
|
headers.replace hash
|
@@ -45,9 +88,14 @@ module Faraday
|
|
45
88
|
end
|
46
89
|
end
|
47
90
|
|
91
|
+
# Update path and params.
|
92
|
+
#
|
93
|
+
# @param path [URI, String]
|
94
|
+
# @param params [Hash, nil]
|
95
|
+
# @return [void]
|
48
96
|
def url(path, params = nil)
|
49
97
|
if path.respond_to? :query
|
50
|
-
if query = path.query
|
98
|
+
if (query = path.query)
|
51
99
|
path = path.dup
|
52
100
|
path.query = nil
|
53
101
|
end
|
@@ -61,34 +109,48 @@ module Faraday
|
|
61
109
|
self.params.update(params) if params
|
62
110
|
end
|
63
111
|
|
112
|
+
# @param key [Object] key to look up in headers
|
113
|
+
# @return [Object] value of the given header name
|
64
114
|
def [](key)
|
65
115
|
headers[key]
|
66
116
|
end
|
67
117
|
|
118
|
+
# @param key [Object] key of header to write
|
119
|
+
# @param value [Object] value of header
|
68
120
|
def []=(key, value)
|
69
121
|
headers[key] = value
|
70
122
|
end
|
71
123
|
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
#
|
87
|
-
#
|
124
|
+
# Marshal serialization support.
|
125
|
+
#
|
126
|
+
# @return [Hash] the hash ready to be serialized in Marshal.
|
127
|
+
def marshal_dump
|
128
|
+
{
|
129
|
+
http_method: http_method,
|
130
|
+
body: body,
|
131
|
+
headers: headers,
|
132
|
+
path: path,
|
133
|
+
params: params,
|
134
|
+
options: options
|
135
|
+
}
|
136
|
+
end
|
137
|
+
|
138
|
+
# Marshal serialization support.
|
139
|
+
# Restores the instance variables according to the +serialised+.
|
140
|
+
# @param serialised [Hash] the serialised object.
|
141
|
+
def marshal_load(serialised)
|
142
|
+
self.http_method = serialised[:http_method]
|
143
|
+
self.body = serialised[:body]
|
144
|
+
self.headers = serialised[:headers]
|
145
|
+
self.path = serialised[:path]
|
146
|
+
self.params = serialised[:params]
|
147
|
+
self.options = serialised[:options]
|
148
|
+
end
|
149
|
+
|
150
|
+
# @return [Env] the Env for this Request
|
88
151
|
def to_env(connection)
|
89
|
-
Env.new(
|
90
|
-
|
152
|
+
Env.new(http_method, body, connection.build_exclusive_url(path, params),
|
153
|
+
options, headers, connection.ssl, connection.parallel_manager)
|
91
154
|
end
|
92
155
|
end
|
93
156
|
end
|
94
|
-
|