faraday 2.6.0 → 2.7.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.md +1 -1
- data/README.md +11 -10
- data/Rakefile +3 -1
- data/lib/faraday/adapter/test.rb +19 -6
- data/lib/faraday/adapter.rb +1 -2
- data/lib/faraday/connection.rb +20 -26
- data/lib/faraday/error.rb +13 -3
- data/lib/faraday/logging/formatter.rb +26 -14
- data/lib/faraday/middleware.rb +3 -0
- data/lib/faraday/options/connection_options.rb +7 -6
- data/lib/faraday/options/env.rb +67 -62
- data/lib/faraday/options/proxy_options.rb +7 -3
- data/lib/faraday/options/request_options.rb +7 -6
- data/lib/faraday/options/ssl_options.rb +51 -50
- data/lib/faraday/options.rb +1 -0
- data/lib/faraday/request/instrumentation.rb +3 -1
- data/lib/faraday/request/json.rb +10 -1
- data/lib/faraday/request.rb +10 -7
- data/lib/faraday/response/logger.rb +4 -0
- data/lib/faraday/response/raise_error.rb +2 -0
- data/lib/faraday/response.rb +2 -1
- data/lib/faraday/utils/headers.rb +6 -1
- data/lib/faraday/version.rb +1 -1
- data/spec/faraday/adapter/test_spec.rb +29 -0
- data/spec/faraday/connection_spec.rb +15 -0
- data/spec/faraday/error_spec.rb +31 -6
- data/spec/faraday/middleware_spec.rb +18 -0
- data/spec/faraday/options/options_spec.rb +1 -1
- data/spec/faraday/options/proxy_options_spec.rb +8 -0
- data/spec/faraday/request/json_spec.rb +24 -0
- data/spec/faraday/response/logger_spec.rb +38 -0
- data/spec/faraday/response/raise_error_spec.rb +12 -0
- data/spec/faraday/response_spec.rb +3 -1
- data/spec/faraday/utils/headers_spec.rb +20 -2
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e4aa57af93476ba31117b14ed37bea950bf9b677d4dcca13ca1296a3ac2c3ff7
|
4
|
+
data.tar.gz: 98b3cb7b7c5c08eba9f58ad96181757d6cd7fc7431ac47ae19e8c95a25de12f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 28f98f568e844799353a00d5ff49511f7bdb759a50edd3de2d4194fbb348dc14d1ef0294d854016ccdcbec915546225ebb2cf6dec354d6e7fbbf707b00cfc170
|
7
|
+
data.tar.gz: 3506cebb9ad1fbd1dd38c1804e18cfd7d7352796d11fa564cde9ce0eee1b1a8ba6d07acda4b179662e5b6eb23baf6f70173240cf8a6b69834d2db9c740a80e25
|
data/LICENSE.md
CHANGED
data/README.md
CHANGED
@@ -4,7 +4,6 @@
|
|
4
4
|
[](https://github.com/lostisland/faraday/actions?query=workflow%3ACI)
|
5
5
|
[](https://github.com/lostisland/faraday/discussions)
|
6
6
|
|
7
|
-
|
8
7
|
Faraday is an HTTP client library abstraction layer that provides a common interface over many
|
9
8
|
adapters (such as Net::HTTP) and embraces the concept of Rack middleware when processing the request/response cycle.
|
10
9
|
You probably don't want to use Faraday directly in your project, as it will lack an actual client library to perform
|
@@ -13,7 +12,8 @@ requests. Instead, you probably want to have a look at [Awesome Faraday][awesome
|
|
13
12
|
## Getting Started
|
14
13
|
|
15
14
|
The best starting point is the [Faraday Website][website], with its introduction and explanation.
|
16
|
-
|
15
|
+
|
16
|
+
Need more details? See the [Faraday API Documentation][apidoc] to see how it works internally, or take a look at [Advanced techniques for calling HTTP APIs in Ruby](https://mattbrictson.com/blog/advanced-http-techniques-in-ruby) blog post from @mattbrictson 🚀
|
17
17
|
|
18
18
|
## Supported Ruby versions
|
19
19
|
|
@@ -42,14 +42,15 @@ Open the issues page and check for the `help wanted` label!
|
|
42
42
|
But before you start coding, please read our [Contributing Guide][contributing]
|
43
43
|
|
44
44
|
## Copyright
|
45
|
-
© 2009 - 2022, the [Faraday Team][faraday_team]. Website and branding design by [Elena Lo Piccolo](https://elelopic.design).
|
46
45
|
|
47
|
-
[
|
48
|
-
|
46
|
+
© 2009 - 2023, the [Faraday Team][faraday_team]. Website and branding design by [Elena Lo Piccolo](https://elelopic.design).
|
47
|
+
|
48
|
+
[awesome]: https://github.com/lostisland/awesome-faraday/#adapters
|
49
|
+
[website]: https://lostisland.github.io/faraday
|
49
50
|
[faraday_team]: https://lostisland.github.io/faraday/team
|
50
51
|
[contributing]: https://github.com/lostisland/faraday/blob/master/.github/CONTRIBUTING.md
|
51
|
-
[apidoc]:
|
52
|
-
[actions]:
|
53
|
-
[jruby]:
|
54
|
-
[rubinius]:
|
55
|
-
[license]:
|
52
|
+
[apidoc]: https://www.rubydoc.info/github/lostisland/faraday
|
53
|
+
[actions]: https://github.com/lostisland/faraday/actions
|
54
|
+
[jruby]: http://jruby.org/
|
55
|
+
[rubinius]: http://rubini.us/
|
56
|
+
[license]: LICENSE.md
|
data/Rakefile
CHANGED
data/lib/faraday/adapter/test.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'timeout'
|
4
|
+
|
3
5
|
module Faraday
|
4
6
|
class Adapter
|
5
7
|
# @example
|
@@ -182,7 +184,7 @@ module Faraday
|
|
182
184
|
end
|
183
185
|
|
184
186
|
# Stub request
|
185
|
-
|
187
|
+
Stub = Struct.new(:host, :path, :query, :headers, :body, :strict_mode, :block) do
|
186
188
|
# @param env [Faraday::Env]
|
187
189
|
def matches?(env)
|
188
190
|
request_host = env[:url].host
|
@@ -238,7 +240,7 @@ module Faraday
|
|
238
240
|
end
|
239
241
|
|
240
242
|
def body_match?(request_body)
|
241
|
-
return true if body.to_s.
|
243
|
+
return true if body.to_s.empty?
|
242
244
|
|
243
245
|
case body
|
244
246
|
when Proc
|
@@ -273,15 +275,26 @@ module Faraday
|
|
273
275
|
|
274
276
|
unless stub
|
275
277
|
raise Stubs::NotFound, "no stubbed request for #{env[:method]} " \
|
276
|
-
"#{env[:url]} #{env[:body]}"
|
278
|
+
"#{env[:url]} #{env[:body]} #{env[:headers]}"
|
277
279
|
end
|
278
280
|
|
279
281
|
block_arity = stub.block.arity
|
282
|
+
params = if block_arity >= 0
|
283
|
+
[env, meta].take(block_arity)
|
284
|
+
else
|
285
|
+
[env, meta]
|
286
|
+
end
|
287
|
+
|
288
|
+
timeout = request_timeout(:open, env[:request])
|
289
|
+
timeout ||= request_timeout(:read, env[:request])
|
290
|
+
|
280
291
|
status, headers, body =
|
281
|
-
if
|
282
|
-
|
292
|
+
if timeout
|
293
|
+
::Timeout.timeout(timeout, Faraday::TimeoutError) do
|
294
|
+
stub.block.call(*params)
|
295
|
+
end
|
283
296
|
else
|
284
|
-
stub.block.call(
|
297
|
+
stub.block.call(*params)
|
285
298
|
end
|
286
299
|
|
287
300
|
# We need to explicitly pass `reason_phrase = nil` here to avoid keyword args conflicts.
|
data/lib/faraday/adapter.rb
CHANGED
@@ -78,8 +78,7 @@ module Faraday
|
|
78
78
|
# @param type [Symbol] Describes which timeout setting to get: :read,
|
79
79
|
# :write, or :open.
|
80
80
|
# @param options [Hash] Hash containing Symbol keys like :timeout,
|
81
|
-
# :read_timeout, :write_timeout, :open_timeout
|
82
|
-
# :timeout
|
81
|
+
# :read_timeout, :write_timeout, or :open_timeout
|
83
82
|
#
|
84
83
|
# @return [Integer, nil] Timeout duration in seconds, or nil if no timeout
|
85
84
|
# has been set.
|
data/lib/faraday/connection.rb
CHANGED
@@ -220,7 +220,7 @@ module Faraday
|
|
220
220
|
# @yield [Faraday::Request] for further request customizations
|
221
221
|
# @return [Faraday::Response]
|
222
222
|
def options(*args)
|
223
|
-
return @options if args.
|
223
|
+
return @options if args.empty?
|
224
224
|
|
225
225
|
url, params, headers = *args
|
226
226
|
run_request(:options, url, nil, headers) do |request|
|
@@ -261,14 +261,13 @@ module Faraday
|
|
261
261
|
# @param headers [Hash, nil] unencoded HTTP header key/value pairs.
|
262
262
|
#
|
263
263
|
# @example
|
264
|
-
#
|
265
|
-
# conn.post '/items', data, content_type: 'application/json'
|
264
|
+
# conn.put '/products/123', data, content_type: 'application/json'
|
266
265
|
#
|
267
|
-
# #
|
268
|
-
# conn.
|
269
|
-
# req.headers[
|
270
|
-
# req.
|
271
|
-
# req.
|
266
|
+
# # Star a gist.
|
267
|
+
# conn.put 'https://api.github.com/gists/GIST_ID/star' do |req|
|
268
|
+
# req.headers['Accept'] = 'application/vnd.github+json'
|
269
|
+
# req.headers['Authorization'] = 'Bearer <YOUR-TOKEN>'
|
270
|
+
# req.headers['X-GitHub-Api-Version'] = '2022-11-28'
|
272
271
|
# end
|
273
272
|
#
|
274
273
|
# @yield [Faraday::Request] for further request customizations
|
@@ -471,10 +470,10 @@ module Faraday
|
|
471
470
|
def build_exclusive_url(url = nil, params = nil, params_encoder = nil)
|
472
471
|
url = nil if url.respond_to?(:empty?) && url.empty?
|
473
472
|
base = url_prefix.dup
|
474
|
-
if url && base.path
|
473
|
+
if url && !base.path.end_with?('/')
|
475
474
|
base.path = "#{base.path}/" # ensure trailing slash
|
476
475
|
end
|
477
|
-
url = url.to_s.gsub(':', '%3A') if
|
476
|
+
url = url.to_s.gsub(':', '%3A') if URI.parse(url.to_s).opaque
|
478
477
|
uri = url ? base + url : base
|
479
478
|
if params
|
480
479
|
uri.query = params.to_query(params_encoder || options.params_encoder)
|
@@ -515,22 +514,17 @@ module Faraday
|
|
515
514
|
return if Faraday.ignore_env_proxy
|
516
515
|
|
517
516
|
uri = nil
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
when nil
|
530
|
-
uri = find_default_proxy
|
531
|
-
end
|
532
|
-
else
|
533
|
-
warn 'no_proxy is unsupported' if ENV['no_proxy'] || ENV['NO_PROXY']
|
517
|
+
case url
|
518
|
+
when String
|
519
|
+
uri = Utils.URI(url)
|
520
|
+
uri = if uri.host.nil?
|
521
|
+
find_default_proxy
|
522
|
+
else
|
523
|
+
URI.parse("#{uri.scheme}://#{uri.host}").find_proxy
|
524
|
+
end
|
525
|
+
when URI
|
526
|
+
uri = url.find_proxy
|
527
|
+
when nil
|
534
528
|
uri = find_default_proxy
|
535
529
|
end
|
536
530
|
ProxyOptions.from(uri) if uri
|
data/lib/faraday/error.rb
CHANGED
@@ -29,15 +29,21 @@ module Faraday
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def response_status
|
32
|
-
|
32
|
+
return unless @response
|
33
|
+
|
34
|
+
@response.is_a?(Faraday::Response) ? @response.status : @response[:status]
|
33
35
|
end
|
34
36
|
|
35
37
|
def response_headers
|
36
|
-
|
38
|
+
return unless @response
|
39
|
+
|
40
|
+
@response.is_a?(Faraday::Response) ? @response.headers : @response[:headers]
|
37
41
|
end
|
38
42
|
|
39
43
|
def response_body
|
40
|
-
|
44
|
+
return unless @response
|
45
|
+
|
46
|
+
@response.is_a?(Faraday::Response) ? @response.body : @response[:body]
|
41
47
|
end
|
42
48
|
|
43
49
|
protected
|
@@ -106,6 +112,10 @@ module Faraday
|
|
106
112
|
class ProxyAuthError < ClientError
|
107
113
|
end
|
108
114
|
|
115
|
+
# Raised by Faraday::Response::RaiseError in case of a 408 response.
|
116
|
+
class RequestTimeoutError < ClientError
|
117
|
+
end
|
118
|
+
|
109
119
|
# Raised by Faraday::Response::RaiseError in case of a 409 response.
|
110
120
|
class ConflictError < ClientError
|
111
121
|
end
|
@@ -8,35 +8,47 @@ module Faraday
|
|
8
8
|
class Formatter
|
9
9
|
extend Forwardable
|
10
10
|
|
11
|
-
DEFAULT_OPTIONS = { headers: true, bodies: false,
|
11
|
+
DEFAULT_OPTIONS = { headers: true, bodies: false, errors: false,
|
12
12
|
log_level: :info }.freeze
|
13
13
|
|
14
14
|
def initialize(logger:, options:)
|
15
15
|
@logger = logger
|
16
|
-
@filter = []
|
17
16
|
@options = DEFAULT_OPTIONS.merge(options)
|
17
|
+
unless %i[debug info warn error fatal].include?(@options[:log_level])
|
18
|
+
@options[:log_level] = :info
|
19
|
+
end
|
20
|
+
@filter = []
|
18
21
|
end
|
19
22
|
|
20
23
|
def_delegators :@logger, :debug, :info, :warn, :error, :fatal
|
21
24
|
|
22
25
|
def request(env)
|
23
|
-
|
26
|
+
public_send(log_level, 'request') do
|
24
27
|
"#{env.method.upcase} #{apply_filters(env.url.to_s)}"
|
25
28
|
end
|
26
|
-
public_send(log_level, 'request', &request_log)
|
27
29
|
|
28
30
|
log_headers('request', env.request_headers) if log_headers?(:request)
|
29
31
|
log_body('request', env[:body]) if env[:body] && log_body?(:request)
|
30
32
|
end
|
31
33
|
|
32
34
|
def response(env)
|
33
|
-
|
34
|
-
public_send(log_level, 'response', &status)
|
35
|
+
public_send(log_level, 'response') { "Status #{env.status}" }
|
35
36
|
|
36
37
|
log_headers('response', env.response_headers) if log_headers?(:response)
|
37
38
|
log_body('response', env[:body]) if env[:body] && log_body?(:response)
|
38
39
|
end
|
39
40
|
|
41
|
+
def exception(exc)
|
42
|
+
return unless log_errors?
|
43
|
+
|
44
|
+
public_send(log_level, 'error') { exc.full_message }
|
45
|
+
|
46
|
+
log_headers('error', exc.response_headers) if exc.respond_to?(:response_headers) && log_headers?(:error)
|
47
|
+
return unless exc.respond_to?(:response_body) && exc.response_body && log_body?(:error)
|
48
|
+
|
49
|
+
log_body('error', exc.response_body)
|
50
|
+
end
|
51
|
+
|
40
52
|
def filter(filter_word, filter_replacement)
|
41
53
|
@filter.push([filter_word, filter_replacement])
|
42
54
|
end
|
@@ -44,6 +56,8 @@ module Faraday
|
|
44
56
|
private
|
45
57
|
|
46
58
|
def dump_headers(headers)
|
59
|
+
return if headers.nil?
|
60
|
+
|
47
61
|
headers.map { |k, v| "#{k}: #{v.inspect}" }.join("\n")
|
48
62
|
end
|
49
63
|
|
@@ -77,6 +91,10 @@ module Faraday
|
|
77
91
|
end
|
78
92
|
end
|
79
93
|
|
94
|
+
def log_errors?
|
95
|
+
@options[:errors]
|
96
|
+
end
|
97
|
+
|
80
98
|
def apply_filters(output)
|
81
99
|
@filter.each do |pattern, replacement|
|
82
100
|
output = output.to_s.gsub(pattern, replacement)
|
@@ -85,21 +103,15 @@ module Faraday
|
|
85
103
|
end
|
86
104
|
|
87
105
|
def log_level
|
88
|
-
unless %i[debug info warn error fatal].include?(@options[:log_level])
|
89
|
-
return :info
|
90
|
-
end
|
91
|
-
|
92
106
|
@options[:log_level]
|
93
107
|
end
|
94
108
|
|
95
109
|
def log_headers(type, headers)
|
96
|
-
|
97
|
-
public_send(log_level, type, &headers_log)
|
110
|
+
public_send(log_level, type) { apply_filters(dump_headers(headers)) }
|
98
111
|
end
|
99
112
|
|
100
113
|
def log_body(type, body)
|
101
|
-
|
102
|
-
public_send(log_level, type, &body_log)
|
114
|
+
public_send(log_level, type) { apply_filters(dump_body(body)) }
|
103
115
|
end
|
104
116
|
end
|
105
117
|
end
|
data/lib/faraday/middleware.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Faraday
|
4
|
-
#
|
5
|
-
#
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
# @!parse
|
5
|
+
# # ConnectionOptions contains the configurable properties for a Faraday
|
6
|
+
# # connection object.
|
7
|
+
# class ConnectionOptions < Options; end
|
8
|
+
ConnectionOptions = Options.new(:request, :proxy, :ssl, :builder, :url,
|
9
|
+
:parallel_manager, :params, :headers,
|
10
|
+
:builder_class) do
|
10
11
|
options request: RequestOptions, ssl: SSLOptions
|
11
12
|
|
12
13
|
memoized(:request) { self.class.options_for(:request).new }
|
data/lib/faraday/options/env.rb
CHANGED
@@ -1,65 +1,70 @@
|
|
1
1
|
# frozen_string_literal: true
|
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
|
-
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
4
|
+
# @!parse
|
5
|
+
# # @!attribute method
|
6
|
+
# # @return [Symbol] HTTP method (`:get`, `:post`)
|
7
|
+
# #
|
8
|
+
# # @!attribute body
|
9
|
+
# # @return [String] The request body that will eventually be converted to a
|
10
|
+
# # string.
|
11
|
+
# #
|
12
|
+
# # @!attribute url
|
13
|
+
# # @return [URI] URI instance for the current request.
|
14
|
+
# #
|
15
|
+
# # @!attribute request
|
16
|
+
# # @return [Hash] options for configuring the request.
|
17
|
+
# # Options for configuring the request.
|
18
|
+
# #
|
19
|
+
# # - `:timeout` - time limit for the entire request (Integer in
|
20
|
+
# # seconds)
|
21
|
+
# # - `:open_timeout` - time limit for just the connection phase (e.g.
|
22
|
+
# # handshake) (Integer in seconds)
|
23
|
+
# # - `:read_timeout` - time limit for the first response byte received from
|
24
|
+
# # the server (Integer in seconds)
|
25
|
+
# # - `:write_timeout` - time limit for the client to send the request to the
|
26
|
+
# # server (Integer in seconds)
|
27
|
+
# # - `:on_data` - Proc for streaming
|
28
|
+
# # - `:proxy` - Hash of proxy options
|
29
|
+
# # - `:uri` - Proxy server URI
|
30
|
+
# # - `:user` - Proxy server username
|
31
|
+
# # - `:password` - Proxy server password
|
32
|
+
# #
|
33
|
+
# # @!attribute request_headers
|
34
|
+
# # @return [Hash] HTTP Headers to be sent to the server.
|
35
|
+
# #
|
36
|
+
# # @!attribute ssl
|
37
|
+
# # @return [Hash] options for configuring SSL requests
|
38
|
+
# #
|
39
|
+
# # @!attribute parallel_manager
|
40
|
+
# # @return [Object] sent if the connection is in parallel mode
|
41
|
+
# #
|
42
|
+
# # @!attribute params
|
43
|
+
# # @return [Hash]
|
44
|
+
# #
|
45
|
+
# # @!attribute response
|
46
|
+
# # @return [Response]
|
47
|
+
# #
|
48
|
+
# # @!attribute response_headers
|
49
|
+
# # @return [Hash] HTTP headers from the server
|
50
|
+
# #
|
51
|
+
# # @!attribute status
|
52
|
+
# # @return [Integer] HTTP response status code
|
53
|
+
# #
|
54
|
+
# # @!attribute reason_phrase
|
55
|
+
# # @return [String]
|
56
|
+
# class Env < Options; end
|
57
|
+
Env = Options.new(:method, :request_body, :url, :request,
|
58
|
+
:request_headers, :ssl, :parallel_manager, :params,
|
59
|
+
:response, :response_headers, :status,
|
60
|
+
:reason_phrase, :response_body) do
|
61
|
+
const_set(:ContentLength, 'Content-Length')
|
62
|
+
const_set(:StatusesWithoutBody, Set.new([204, 304]))
|
63
|
+
const_set(:SuccessfulStatuses, (200..299).freeze)
|
59
64
|
|
60
65
|
# A Set of HTTP verbs that typically send a body. If no body is set for
|
61
66
|
# these requests, the Content-Length header is set to 0.
|
62
|
-
MethodsWithBodies
|
67
|
+
const_set(:MethodsWithBodies, Set.new(Faraday::METHODS_WITH_BODY.map(&:to_sym)))
|
63
68
|
|
64
69
|
options request: RequestOptions,
|
65
70
|
request_headers: Utils::Headers, response_headers: Utils::Headers
|
@@ -120,25 +125,25 @@ module Faraday
|
|
120
125
|
|
121
126
|
# @return [Boolean] true if status is in the set of {SuccessfulStatuses}.
|
122
127
|
def success?
|
123
|
-
SuccessfulStatuses.include?(status)
|
128
|
+
Env::SuccessfulStatuses.include?(status)
|
124
129
|
end
|
125
130
|
|
126
131
|
# @return [Boolean] true if there's no body yet, and the method is in the
|
127
|
-
# set of {MethodsWithBodies}.
|
132
|
+
# set of {Env::MethodsWithBodies}.
|
128
133
|
def needs_body?
|
129
|
-
!body && MethodsWithBodies.include?(method)
|
134
|
+
!body && Env::MethodsWithBodies.include?(method)
|
130
135
|
end
|
131
136
|
|
132
137
|
# Sets content length to zero and the body to the empty string.
|
133
138
|
def clear_body
|
134
|
-
request_headers[ContentLength] = '0'
|
139
|
+
request_headers[Env::ContentLength] = '0'
|
135
140
|
self.body = +''
|
136
141
|
end
|
137
142
|
|
138
143
|
# @return [Boolean] true if the status isn't in the set of
|
139
|
-
# {StatusesWithoutBody}.
|
144
|
+
# {Env::StatusesWithoutBody}.
|
140
145
|
def parse_body?
|
141
|
-
!StatusesWithoutBody.include?(status)
|
146
|
+
!Env::StatusesWithoutBody.include?(status)
|
142
147
|
end
|
143
148
|
|
144
149
|
# @return [Boolean] true if there is a parallel_manager
|
@@ -1,15 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Faraday
|
4
|
-
#
|
5
|
-
#
|
6
|
-
|
4
|
+
# @!parse
|
5
|
+
# # ProxyOptions contains the configurable properties for the proxy
|
6
|
+
# # configuration used when making an HTTP request.
|
7
|
+
# class ProxyOptions < Options; end
|
8
|
+
ProxyOptions = Options.new(:uri, :user, :password) do
|
7
9
|
extend Forwardable
|
8
10
|
def_delegators :uri, :scheme, :scheme=, :host, :host=, :port, :port=,
|
9
11
|
:path, :path=
|
10
12
|
|
11
13
|
def self.from(value)
|
12
14
|
case value
|
15
|
+
when ''
|
16
|
+
value = nil
|
13
17
|
when String
|
14
18
|
# URIs without a scheme should default to http (like 'example:123').
|
15
19
|
# This fixes #1282 and prevents a silent failure in some adapters.
|
@@ -1,12 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Faraday
|
4
|
-
#
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
# @!parse
|
5
|
+
# # RequestOptions contains the configurable properties for a Faraday request.
|
6
|
+
# class RequestOptions < Options; end
|
7
|
+
RequestOptions = Options.new(:params_encoder, :proxy, :bind,
|
8
|
+
:timeout, :open_timeout, :read_timeout,
|
9
|
+
:write_timeout, :boundary, :oauth,
|
10
|
+
:context, :on_data) do
|
10
11
|
def []=(key, value)
|
11
12
|
if key && key.to_sym == :proxy
|
12
13
|
super(key, value ? ProxyOptions.from(value) : nil)
|
@@ -1,56 +1,57 @@
|
|
1
1
|
# frozen_string_literal: true
|
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
|
-
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
4
|
+
# @!parse
|
5
|
+
# # SSL-related options.
|
6
|
+
# #
|
7
|
+
# # @!attribute verify
|
8
|
+
# # @return [Boolean] whether to verify SSL certificates or not
|
9
|
+
# #
|
10
|
+
# # @!attribute verify_hostname
|
11
|
+
# # @return [Boolean] whether to enable hostname verification on server certificates
|
12
|
+
# # during the handshake or not (see https://github.com/ruby/openssl/pull/60)
|
13
|
+
# #
|
14
|
+
# # @!attribute ca_file
|
15
|
+
# # @return [String] CA file
|
16
|
+
# #
|
17
|
+
# # @!attribute ca_path
|
18
|
+
# # @return [String] CA path
|
19
|
+
# #
|
20
|
+
# # @!attribute verify_mode
|
21
|
+
# # @return [Integer] Any `OpenSSL::SSL::` constant (see https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL/SSL.html)
|
22
|
+
# #
|
23
|
+
# # @!attribute cert_store
|
24
|
+
# # @return [OpenSSL::X509::Store] certificate store
|
25
|
+
# #
|
26
|
+
# # @!attribute client_cert
|
27
|
+
# # @return [String, OpenSSL::X509::Certificate] client certificate
|
28
|
+
# #
|
29
|
+
# # @!attribute client_key
|
30
|
+
# # @return [String, OpenSSL::PKey::RSA, OpenSSL::PKey::DSA] client key
|
31
|
+
# #
|
32
|
+
# # @!attribute certificate
|
33
|
+
# # @return [OpenSSL::X509::Certificate] certificate (Excon only)
|
34
|
+
# #
|
35
|
+
# # @!attribute private_key
|
36
|
+
# # @return [OpenSSL::PKey::RSA, OpenSSL::PKey::DSA] private key (Excon only)
|
37
|
+
# #
|
38
|
+
# # @!attribute verify_depth
|
39
|
+
# # @return [Integer] maximum depth for the certificate chain verification
|
40
|
+
# #
|
41
|
+
# # @!attribute version
|
42
|
+
# # @return [String, Symbol] SSL version (see https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html#method-i-ssl_version-3D)
|
43
|
+
# #
|
44
|
+
# # @!attribute min_version
|
45
|
+
# # @return [String, Symbol] minimum SSL version (see https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html#method-i-min_version-3D)
|
46
|
+
# #
|
47
|
+
# # @!attribute max_version
|
48
|
+
# # @return [String, Symbol] maximum SSL version (see https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html#method-i-max_version-3D)
|
49
|
+
# class SSLOptions < Options; end
|
50
|
+
SSLOptions = Options.new(:verify, :verify_hostname,
|
51
|
+
:ca_file, :ca_path, :verify_mode,
|
52
|
+
:cert_store, :client_cert, :client_key,
|
53
|
+
:certificate, :private_key, :verify_depth,
|
54
|
+
:version, :min_version, :max_version) do
|
54
55
|
# @return [Boolean] true if should verify
|
55
56
|
def verify?
|
56
57
|
verify != false
|
data/lib/faraday/options.rb
CHANGED
@@ -5,12 +5,14 @@ module Faraday
|
|
5
5
|
# Middleware for instrumenting Requests.
|
6
6
|
class Instrumentation < Faraday::Middleware
|
7
7
|
# Options class used in Request::Instrumentation class.
|
8
|
-
|
8
|
+
Options = Faraday::Options.new(:name, :instrumenter) do
|
9
|
+
remove_method :name
|
9
10
|
# @return [String]
|
10
11
|
def name
|
11
12
|
self[:name] ||= 'request.faraday'
|
12
13
|
end
|
13
14
|
|
15
|
+
remove_method :instrumenter
|
14
16
|
# @return [Class]
|
15
17
|
def instrumenter
|
16
18
|
self[:instrumenter] ||= ActiveSupport::Notifications
|
data/lib/faraday/request/json.rb
CHANGED
@@ -40,7 +40,16 @@ module Faraday
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def body?(env)
|
43
|
-
|
43
|
+
body = env[:body]
|
44
|
+
case body
|
45
|
+
when true, false
|
46
|
+
true
|
47
|
+
when nil
|
48
|
+
# NOTE: nil can be converted to `"null"`, but this middleware doesn't process `nil` for the compatibility.
|
49
|
+
false
|
50
|
+
else
|
51
|
+
!(body.respond_to?(:to_str) && body.empty?)
|
52
|
+
end
|
44
53
|
end
|
45
54
|
|
46
55
|
def request_type(env)
|
data/lib/faraday/request.rb
CHANGED
@@ -24,13 +24,14 @@ module Faraday
|
|
24
24
|
# @return [String] body
|
25
25
|
# @!attribute options
|
26
26
|
# @return [RequestOptions] options
|
27
|
-
|
28
|
-
# rubocop:disable Style/StructInheritance
|
29
|
-
class Request < Struct.new(:http_method, :path, :params, :headers, :body, :options)
|
30
|
-
# rubocop:enable Style/StructInheritance
|
31
|
-
|
27
|
+
Request = Struct.new(:http_method, :path, :params, :headers, :body, :options) do
|
32
28
|
extend MiddlewareRegistry
|
33
29
|
|
30
|
+
alias_method :member_get, :[]
|
31
|
+
private :member_get
|
32
|
+
alias_method :member_set, :[]=
|
33
|
+
private :member_set
|
34
|
+
|
34
35
|
# @param request_method [String]
|
35
36
|
# @yield [request] for block customization, if block given
|
36
37
|
# @yieldparam request [Request]
|
@@ -41,6 +42,7 @@ module Faraday
|
|
41
42
|
end
|
42
43
|
end
|
43
44
|
|
45
|
+
remove_method :params=
|
44
46
|
# Replace params, preserving the existing hash type.
|
45
47
|
#
|
46
48
|
# @param hash [Hash] new params
|
@@ -48,10 +50,11 @@ module Faraday
|
|
48
50
|
if params
|
49
51
|
params.replace hash
|
50
52
|
else
|
51
|
-
|
53
|
+
member_set(:params, hash)
|
52
54
|
end
|
53
55
|
end
|
54
56
|
|
57
|
+
remove_method :headers=
|
55
58
|
# Replace request headers, preserving the existing hash type.
|
56
59
|
#
|
57
60
|
# @param hash [Hash] new headers
|
@@ -59,7 +62,7 @@ module Faraday
|
|
59
62
|
if headers
|
60
63
|
headers.replace hash
|
61
64
|
else
|
62
|
-
|
65
|
+
member_set(:headers, hash)
|
63
66
|
end
|
64
67
|
end
|
65
68
|
|
@@ -24,6 +24,8 @@ module Faraday
|
|
24
24
|
# mimic the behavior that we get with proxy requests with HTTPS
|
25
25
|
msg = %(407 "Proxy Authentication Required")
|
26
26
|
raise Faraday::ProxyAuthError.new(msg, response_values(env))
|
27
|
+
when 408
|
28
|
+
raise Faraday::RequestTimeoutError, response_values(env)
|
27
29
|
when 409
|
28
30
|
raise Faraday::ConflictError, response_values(env)
|
29
31
|
when 422
|
data/lib/faraday/response.rb
CHANGED
@@ -132,7 +132,12 @@ module Faraday
|
|
132
132
|
|
133
133
|
# Join multiple values with a comma.
|
134
134
|
def add_parsed(key, value)
|
135
|
-
|
135
|
+
if key?(key)
|
136
|
+
self[key] = self[key].to_s
|
137
|
+
self[key] << ', ' << value
|
138
|
+
else
|
139
|
+
self[key] = value
|
140
|
+
end
|
136
141
|
end
|
137
142
|
end
|
138
143
|
end
|
data/lib/faraday/version.rb
CHANGED
@@ -410,4 +410,33 @@ RSpec.describe Faraday::Adapter::Test do
|
|
410
410
|
end
|
411
411
|
end
|
412
412
|
end
|
413
|
+
|
414
|
+
describe 'request timeout' do
|
415
|
+
subject(:request) do
|
416
|
+
connection.get('/sleep') do |req|
|
417
|
+
req.options.timeout = timeout
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
before do
|
422
|
+
stubs.get('/sleep') do
|
423
|
+
sleep(0.01)
|
424
|
+
[200, {}, '']
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
context 'when request is within timeout' do
|
429
|
+
let(:timeout) { 1 }
|
430
|
+
|
431
|
+
it { expect(request.status).to eq 200 }
|
432
|
+
end
|
433
|
+
|
434
|
+
context 'when request is too slow' do
|
435
|
+
let(:timeout) { 0.001 }
|
436
|
+
|
437
|
+
it 'raises an exception' do
|
438
|
+
expect { request }.to raise_error(Faraday::TimeoutError)
|
439
|
+
end
|
440
|
+
end
|
441
|
+
end
|
413
442
|
end
|
@@ -310,6 +310,21 @@ RSpec.describe Faraday::Connection do
|
|
310
310
|
expect(uri.to_s).to eq('http://service.com/api/service%3Asearch?limit=400')
|
311
311
|
end
|
312
312
|
end
|
313
|
+
|
314
|
+
context 'with a custom `default_uri_parser`' do
|
315
|
+
let(:url) { 'http://httpbingo.org' }
|
316
|
+
let(:parser) { Addressable::URI }
|
317
|
+
|
318
|
+
around do |example|
|
319
|
+
with_default_uri_parser(parser) do
|
320
|
+
example.run
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
it 'does not raise error' do
|
325
|
+
expect { conn.build_exclusive_url('/nigiri') }.not_to raise_error
|
326
|
+
end
|
327
|
+
end
|
313
328
|
end
|
314
329
|
|
315
330
|
describe '#build_url' do
|
data/spec/faraday/error_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
RSpec.describe Faraday::
|
3
|
+
RSpec.describe Faraday::Error do
|
4
4
|
describe '.initialize' do
|
5
5
|
subject { described_class.new(exception, response) }
|
6
6
|
let(:response) { nil }
|
@@ -12,8 +12,10 @@ RSpec.describe Faraday::ClientError do
|
|
12
12
|
it { expect(subject.response).to be_nil }
|
13
13
|
it { expect(subject.message).to eq(exception.message) }
|
14
14
|
it { expect(subject.backtrace).to eq(exception.backtrace) }
|
15
|
-
it { expect(subject.inspect).to eq('#<Faraday::
|
15
|
+
it { expect(subject.inspect).to eq('#<Faraday::Error wrapped=#<RuntimeError: test>>') }
|
16
16
|
it { expect(subject.response_status).to be_nil }
|
17
|
+
it { expect(subject.response_headers).to be_nil }
|
18
|
+
it { expect(subject.response_body).to be_nil }
|
17
19
|
end
|
18
20
|
|
19
21
|
context 'with response hash' do
|
@@ -22,8 +24,10 @@ RSpec.describe Faraday::ClientError do
|
|
22
24
|
it { expect(subject.wrapped_exception).to be_nil }
|
23
25
|
it { expect(subject.response).to eq(exception) }
|
24
26
|
it { expect(subject.message).to eq('the server responded with status 400') }
|
25
|
-
it { expect(subject.inspect).to eq('#<Faraday::
|
27
|
+
it { expect(subject.inspect).to eq('#<Faraday::Error response={:status=>400}>') }
|
26
28
|
it { expect(subject.response_status).to eq(400) }
|
29
|
+
it { expect(subject.response_headers).to be_nil }
|
30
|
+
it { expect(subject.response_body).to be_nil }
|
27
31
|
end
|
28
32
|
|
29
33
|
context 'with string' do
|
@@ -32,8 +36,10 @@ RSpec.describe Faraday::ClientError do
|
|
32
36
|
it { expect(subject.wrapped_exception).to be_nil }
|
33
37
|
it { expect(subject.response).to be_nil }
|
34
38
|
it { expect(subject.message).to eq('custom message') }
|
35
|
-
it { expect(subject.inspect).to eq('#<Faraday::
|
39
|
+
it { expect(subject.inspect).to eq('#<Faraday::Error #<Faraday::Error: custom message>>') }
|
36
40
|
it { expect(subject.response_status).to be_nil }
|
41
|
+
it { expect(subject.response_headers).to be_nil }
|
42
|
+
it { expect(subject.response_body).to be_nil }
|
37
43
|
end
|
38
44
|
|
39
45
|
context 'with anything else #to_s' do
|
@@ -42,8 +48,10 @@ RSpec.describe Faraday::ClientError do
|
|
42
48
|
it { expect(subject.wrapped_exception).to be_nil }
|
43
49
|
it { expect(subject.response).to be_nil }
|
44
50
|
it { expect(subject.message).to eq('["error1", "error2"]') }
|
45
|
-
it { expect(subject.inspect).to eq('#<Faraday::
|
51
|
+
it { expect(subject.inspect).to eq('#<Faraday::Error #<Faraday::Error: ["error1", "error2"]>>') }
|
46
52
|
it { expect(subject.response_status).to be_nil }
|
53
|
+
it { expect(subject.response_headers).to be_nil }
|
54
|
+
it { expect(subject.response_body).to be_nil }
|
47
55
|
end
|
48
56
|
|
49
57
|
context 'with exception string and response hash' do
|
@@ -53,8 +61,25 @@ RSpec.describe Faraday::ClientError do
|
|
53
61
|
it { expect(subject.wrapped_exception).to be_nil }
|
54
62
|
it { expect(subject.response).to eq(response) }
|
55
63
|
it { expect(subject.message).to eq('custom message') }
|
56
|
-
it { expect(subject.inspect).to eq('#<Faraday::
|
64
|
+
it { expect(subject.inspect).to eq('#<Faraday::Error response={:status=>400}>') }
|
57
65
|
it { expect(subject.response_status).to eq(400) }
|
66
|
+
it { expect(subject.response_headers).to be_nil }
|
67
|
+
it { expect(subject.response_body).to be_nil }
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'with exception and response object' do
|
71
|
+
let(:exception) { RuntimeError.new('test') }
|
72
|
+
let(:body) { { test: 'test' } }
|
73
|
+
let(:headers) { { 'Content-Type' => 'application/json' } }
|
74
|
+
let(:response) { Faraday::Response.new(status: 400, response_headers: headers, response_body: body) }
|
75
|
+
|
76
|
+
it { expect(subject.wrapped_exception).to eq(exception) }
|
77
|
+
it { expect(subject.response).to eq(response) }
|
78
|
+
it { expect(subject.message).to eq(exception.message) }
|
79
|
+
it { expect(subject.backtrace).to eq(exception.backtrace) }
|
80
|
+
it { expect(subject.response_status).to eq(400) }
|
81
|
+
it { expect(subject.response_headers).to eq(headers) }
|
82
|
+
it { expect(subject.response_body).to eq(body) }
|
58
83
|
end
|
59
84
|
end
|
60
85
|
end
|
@@ -33,6 +33,24 @@ RSpec.describe Faraday::Middleware do
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
+
describe '#on_error' do
|
37
|
+
subject do
|
38
|
+
Class.new(described_class) do
|
39
|
+
def on_error(error)
|
40
|
+
# do nothing
|
41
|
+
end
|
42
|
+
end.new(app)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'is called by #call' do
|
46
|
+
expect(app).to receive(:call).and_raise(Faraday::ConnectionFailed)
|
47
|
+
is_expected.to receive(:call).and_call_original
|
48
|
+
is_expected.to receive(:on_error)
|
49
|
+
|
50
|
+
expect { subject.call(double) }.to raise_error(Faraday::ConnectionFailed)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
36
54
|
describe '#close' do
|
37
55
|
context "with app that doesn't support \#close" do
|
38
56
|
it 'should issue warning' do
|
@@ -32,6 +32,14 @@ RSpec.describe Faraday::ProxyOptions do
|
|
32
32
|
expect(proxy.user).to be_nil
|
33
33
|
expect(proxy.password).to be_nil
|
34
34
|
end
|
35
|
+
|
36
|
+
it 'treats empty string as nil' do
|
37
|
+
proxy = nil
|
38
|
+
proxy_string = proxy.to_s # => empty string
|
39
|
+
options = Faraday::ProxyOptions.from proxy_string
|
40
|
+
expect(options).to be_a_kind_of(Faraday::ProxyOptions)
|
41
|
+
expect(options.inspect).to eq('#<Faraday::ProxyOptions (empty)>')
|
42
|
+
end
|
35
43
|
end
|
36
44
|
|
37
45
|
it 'allows hash access' do
|
@@ -73,6 +73,30 @@ RSpec.describe Faraday::Request::Json do
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
+
context 'true body' do
|
77
|
+
let(:result) { process(true) }
|
78
|
+
|
79
|
+
it 'encodes body' do
|
80
|
+
expect(result_body).to eq('true')
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'adds content type' do
|
84
|
+
expect(result_type).to eq('application/json')
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'false body' do
|
89
|
+
let(:result) { process(false) }
|
90
|
+
|
91
|
+
it 'encodes body' do
|
92
|
+
expect(result_body).to eq('false')
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'adds content type' do
|
96
|
+
expect(result_type).to eq('application/json')
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
76
100
|
context 'object body with json type' do
|
77
101
|
let(:result) { process({ a: 1 }, 'application/json; charset=utf-8') }
|
78
102
|
|
@@ -25,6 +25,7 @@ RSpec.describe Faraday::Response::Logger do
|
|
25
25
|
stubs.get('/filtered_headers') { [200, { 'Content-Type' => 'text/html' }, 'headers response'] }
|
26
26
|
stubs.get('/filtered_params') { [200, { 'Content-Type' => 'text/html' }, 'params response'] }
|
27
27
|
stubs.get('/filtered_url') { [200, { 'Content-Type' => 'text/html' }, 'url response'] }
|
28
|
+
stubs.get('/connection_failed') { raise Faraday::ConnectionFailed, 'Failed to open TCP connection' }
|
28
29
|
end
|
29
30
|
end
|
30
31
|
end
|
@@ -64,6 +65,15 @@ RSpec.describe Faraday::Response::Logger do
|
|
64
65
|
expect(formatter).to receive(:response).with(an_instance_of(Faraday::Env))
|
65
66
|
conn.get '/hello'
|
66
67
|
end
|
68
|
+
|
69
|
+
context 'when no route' do
|
70
|
+
it 'delegates logging to the formatter' do
|
71
|
+
expect(formatter).to receive(:request).with(an_instance_of(Faraday::Env))
|
72
|
+
expect(formatter).to receive(:exception).with(an_instance_of(Faraday::Adapter::Test::Stubs::NotFound))
|
73
|
+
|
74
|
+
expect { conn.get '/noroute' }.to raise_error(Faraday::Adapter::Test::Stubs::NotFound)
|
75
|
+
end
|
76
|
+
end
|
67
77
|
end
|
68
78
|
|
69
79
|
context 'with custom formatter' do
|
@@ -94,6 +104,16 @@ RSpec.describe Faraday::Response::Logger do
|
|
94
104
|
expect(string_io.string).to match('GET http:/hello')
|
95
105
|
end
|
96
106
|
|
107
|
+
it 'logs status' do
|
108
|
+
conn.get '/hello', nil, accept: 'text/html'
|
109
|
+
expect(string_io.string).to match('Status 200')
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'does not log error message by default' do
|
113
|
+
expect { conn.get '/noroute' }.to raise_error(Faraday::Adapter::Test::Stubs::NotFound)
|
114
|
+
expect(string_io.string).not_to match(%(no stubbed request for get http:/noroute))
|
115
|
+
end
|
116
|
+
|
97
117
|
it 'logs request headers by default' do
|
98
118
|
conn.get '/hello', nil, accept: 'text/html'
|
99
119
|
expect(string_io.string).to match(%(Accept: "text/html))
|
@@ -188,6 +208,24 @@ RSpec.describe Faraday::Response::Logger do
|
|
188
208
|
end
|
189
209
|
end
|
190
210
|
|
211
|
+
context 'when logging errors' do
|
212
|
+
let(:logger_options) { { errors: true } }
|
213
|
+
|
214
|
+
it 'logs error message' do
|
215
|
+
expect { conn.get '/noroute' }.to raise_error(Faraday::Adapter::Test::Stubs::NotFound)
|
216
|
+
expect(string_io.string).to match(%(no stubbed request for get http:/noroute))
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
context 'when logging headers and errors' do
|
221
|
+
let(:logger_options) { { headers: true, errors: true } }
|
222
|
+
|
223
|
+
it 'logs error message' do
|
224
|
+
expect { conn.get '/connection_failed' }.to raise_error(Faraday::ConnectionFailed)
|
225
|
+
expect(string_io.string).to match(%(Failed to open TCP connection))
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
191
229
|
context 'when using log_level' do
|
192
230
|
let(:logger_options) { { bodies: true, log_level: :debug } }
|
193
231
|
|
@@ -11,6 +11,7 @@ RSpec.describe Faraday::Response::RaiseError do
|
|
11
11
|
stub.get('forbidden') { [403, { 'X-Reason' => 'because' }, 'keep looking'] }
|
12
12
|
stub.get('not-found') { [404, { 'X-Reason' => 'because' }, 'keep looking'] }
|
13
13
|
stub.get('proxy-error') { [407, { 'X-Reason' => 'because' }, 'keep looking'] }
|
14
|
+
stub.get('request-timeout') { [408, { 'X-Reason' => 'because' }, 'keep looking'] }
|
14
15
|
stub.get('conflict') { [409, { 'X-Reason' => 'because' }, 'keep looking'] }
|
15
16
|
stub.get('unprocessable-entity') { [422, { 'X-Reason' => 'because' }, 'keep looking'] }
|
16
17
|
stub.get('4xx') { [499, { 'X-Reason' => 'because' }, 'keep looking'] }
|
@@ -79,6 +80,17 @@ RSpec.describe Faraday::Response::RaiseError do
|
|
79
80
|
end
|
80
81
|
end
|
81
82
|
|
83
|
+
it 'raises Faraday::RequestTimeoutError for 408 responses' do
|
84
|
+
expect { conn.get('request-timeout') }.to raise_error(Faraday::RequestTimeoutError) do |ex|
|
85
|
+
expect(ex.message).to eq('the server responded with status 408')
|
86
|
+
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
87
|
+
expect(ex.response[:status]).to eq(408)
|
88
|
+
expect(ex.response_status).to eq(408)
|
89
|
+
expect(ex.response_body).to eq('keep looking')
|
90
|
+
expect(ex.response_headers['X-Reason']).to eq('because')
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
82
94
|
it 'raises Faraday::ConflictError for 409 responses' do
|
83
95
|
expect { conn.get('conflict') }.to raise_error(Faraday::ConflictError) do |ex|
|
84
96
|
expect(ex.message).to eq('the server responded with status 409')
|
@@ -4,7 +4,7 @@ RSpec.describe Faraday::Response do
|
|
4
4
|
subject { Faraday::Response.new(env) }
|
5
5
|
|
6
6
|
let(:env) do
|
7
|
-
Faraday::Env.from(status: 404, body: 'yikes',
|
7
|
+
Faraday::Env.from(status: 404, body: 'yikes', url: Faraday::Utils.URI('https://lostisland.github.io/faraday'),
|
8
8
|
response_headers: { 'Content-Type' => 'text/plain' })
|
9
9
|
end
|
10
10
|
|
@@ -30,6 +30,7 @@ RSpec.describe Faraday::Response do
|
|
30
30
|
it { expect(hash[:status]).to eq(subject.status) }
|
31
31
|
it { expect(hash[:response_headers]).to eq(subject.headers) }
|
32
32
|
it { expect(hash[:body]).to eq(subject.body) }
|
33
|
+
it { expect(hash[:url]).to eq(subject.env.url) }
|
33
34
|
end
|
34
35
|
|
35
36
|
describe 'marshal serialization support' do
|
@@ -45,6 +46,7 @@ RSpec.describe Faraday::Response do
|
|
45
46
|
it { expect(loaded.env[:body]).to eq(env[:body]) }
|
46
47
|
it { expect(loaded.env[:response_headers]).to eq(env[:response_headers]) }
|
47
48
|
it { expect(loaded.env[:status]).to eq(env[:status]) }
|
49
|
+
it { expect(loaded.env[:url]).to eq(env[:url]) }
|
48
50
|
end
|
49
51
|
|
50
52
|
describe '#on_complete' do
|
@@ -57,11 +57,11 @@ RSpec.describe Faraday::Utils::Headers do
|
|
57
57
|
end
|
58
58
|
|
59
59
|
describe '#parse' do
|
60
|
-
before { subject.parse(headers) }
|
61
|
-
|
62
60
|
context 'when response headers leave http status line out' do
|
63
61
|
let(:headers) { "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n" }
|
64
62
|
|
63
|
+
before { subject.parse(headers) }
|
64
|
+
|
65
65
|
it { expect(subject.keys).to eq(%w[Content-Type]) }
|
66
66
|
it { expect(subject['Content-Type']).to eq('text/html') }
|
67
67
|
it { expect(subject['content-type']).to eq('text/html') }
|
@@ -70,13 +70,31 @@ RSpec.describe Faraday::Utils::Headers do
|
|
70
70
|
context 'when response headers values include a colon' do
|
71
71
|
let(:headers) { "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nLocation: http://httpbingo.org/\r\n\r\n" }
|
72
72
|
|
73
|
+
before { subject.parse(headers) }
|
74
|
+
|
73
75
|
it { expect(subject['location']).to eq('http://httpbingo.org/') }
|
74
76
|
end
|
75
77
|
|
76
78
|
context 'when response headers include a blank line' do
|
77
79
|
let(:headers) { "HTTP/1.1 200 OK\r\n\r\nContent-Type: text/html\r\n\r\n" }
|
78
80
|
|
81
|
+
before { subject.parse(headers) }
|
82
|
+
|
79
83
|
it { expect(subject['content-type']).to eq('text/html') }
|
80
84
|
end
|
85
|
+
|
86
|
+
context 'when response headers include already stored keys' do
|
87
|
+
let(:headers) { "HTTP/1.1 200 OK\r\nX-Numbers: 123\r\n\r\n" }
|
88
|
+
|
89
|
+
before do
|
90
|
+
h = subject
|
91
|
+
h[:x_numbers] = 8
|
92
|
+
h.parse(headers)
|
93
|
+
end
|
94
|
+
|
95
|
+
it do
|
96
|
+
expect(subject[:x_numbers]).to eq('8, 123')
|
97
|
+
end
|
98
|
+
end
|
81
99
|
end
|
82
100
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: faraday
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.7.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- "@technoweenie"
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2023-07-06 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: faraday-net_http
|
@@ -131,7 +131,7 @@ licenses:
|
|
131
131
|
- MIT
|
132
132
|
metadata:
|
133
133
|
homepage_uri: https://lostisland.github.io/faraday
|
134
|
-
changelog_uri: https://github.com/lostisland/faraday/releases/tag/v2.
|
134
|
+
changelog_uri: https://github.com/lostisland/faraday/releases/tag/v2.7.10
|
135
135
|
source_code_uri: https://github.com/lostisland/faraday
|
136
136
|
bug_tracker_uri: https://github.com/lostisland/faraday/issues
|
137
137
|
post_install_message:
|