faraday 0.9.1 → 0.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +196 -0
- data/LICENSE.md +1 -1
- data/README.md +192 -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 +36 -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 +101 -0
- data/lib/faraday/error.rb +90 -24
- data/lib/faraday/options.rb +43 -20
- data/lib/faraday/parameters.rb +56 -39
- data/lib/faraday/rack_builder.rb +27 -2
- 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 +14 -34
- data/spec/faraday/deprecate_spec.rb +69 -0
- data/spec/faraday/error_spec.rb +102 -0
- data/spec/faraday/response/raise_error_spec.rb +95 -0
- data/spec/spec_helper.rb +104 -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
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: 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.1"
|
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
|
#
|
@@ -66,7 +66,7 @@ module Faraday
|
|
66
66
|
# Returns a Faraday::Connection.
|
67
67
|
def new(url = nil, options = nil)
|
68
68
|
block = block_given? ? Proc.new : nil
|
69
|
-
options = options ? default_connection_options.merge(options) : default_connection_options
|
69
|
+
options = options ? default_connection_options.merge(options) : default_connection_options
|
70
70
|
Faraday::Connection.new(url, options, &block)
|
71
71
|
end
|
72
72
|
|
@@ -92,6 +92,10 @@ module Faraday
|
|
92
92
|
|
93
93
|
alias require_lib require_libs
|
94
94
|
|
95
|
+
def respond_to?(symbol, include_private = false)
|
96
|
+
default_connection.respond_to?(symbol, include_private) || super
|
97
|
+
end
|
98
|
+
|
95
99
|
private
|
96
100
|
# Internal: Proxies method calls on the Faraday constant to
|
97
101
|
# #default_connection.
|
@@ -100,6 +104,7 @@ module Faraday
|
|
100
104
|
end
|
101
105
|
end
|
102
106
|
|
107
|
+
self.ignore_env_proxy = false
|
103
108
|
self.root_path = File.expand_path "..", __FILE__
|
104
109
|
self.lib_path = File.expand_path "../faraday", __FILE__
|
105
110
|
self.default_adapter = :net_http
|
@@ -108,7 +113,7 @@ module Faraday
|
|
108
113
|
#
|
109
114
|
# Returns a Faraday::Connection, configured with the #default_adapter.
|
110
115
|
def self.default_connection
|
111
|
-
@default_connection ||= Connection.new
|
116
|
+
@default_connection ||= Connection.new(default_connection_options)
|
112
117
|
end
|
113
118
|
|
114
119
|
# Gets the default connection options used when calling Faraday#new.
|
@@ -118,13 +123,10 @@ module Faraday
|
|
118
123
|
@default_connection_options ||= ConnectionOptions.new
|
119
124
|
end
|
120
125
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
rescue LoadError
|
126
|
-
warn "Faraday: you may want to install system_timer for reliable timeouts"
|
127
|
-
end
|
126
|
+
# Public: Sets the default options used when calling Faraday#new.
|
127
|
+
def self.default_connection_options=(options)
|
128
|
+
@default_connection = nil
|
129
|
+
@default_connection_options = ConnectionOptions.from(options)
|
128
130
|
end
|
129
131
|
|
130
132
|
unless const_defined? :Timer
|
@@ -244,25 +246,3 @@ module Faraday
|
|
244
246
|
require_lib 'autoload'
|
245
247
|
end
|
246
248
|
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,69 @@
|
|
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
|
+
|
60
|
+
def with_warn_squelching
|
61
|
+
stderr_catcher = StringIO.new
|
62
|
+
original_stderr = $stderr
|
63
|
+
$stderr = stderr_catcher
|
64
|
+
result = yield if block_given?
|
65
|
+
[stderr_catcher.tap(&:rewind).string, result]
|
66
|
+
ensure
|
67
|
+
$stderr = original_stderr
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Faraday::ClientError do
|
4
|
+
describe '.initialize' do
|
5
|
+
subject { described_class.new(exception, response) }
|
6
|
+
let(:response) { nil }
|
7
|
+
|
8
|
+
context 'with exception only' do
|
9
|
+
let(:exception) { RuntimeError.new('test') }
|
10
|
+
|
11
|
+
it { expect(subject.wrapped_exception).to eq(exception) }
|
12
|
+
it { expect(subject.response).to be_nil }
|
13
|
+
it { expect(subject.message).to eq(exception.message) }
|
14
|
+
it { expect(subject.backtrace).to eq(exception.backtrace) }
|
15
|
+
it { expect(subject.inspect).to eq('#<Faraday::ClientError wrapped=#<RuntimeError: test>>') }
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'with response hash' do
|
19
|
+
let(:exception) { { status: 400 } }
|
20
|
+
|
21
|
+
it { expect(subject.wrapped_exception).to be_nil }
|
22
|
+
it { expect(subject.response).to eq(exception) }
|
23
|
+
it { expect(subject.message).to eq('the server responded with status 400') }
|
24
|
+
it { expect(subject.inspect).to eq('#<Faraday::ClientError response={:status=>400}>') }
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'with string' do
|
28
|
+
let(:exception) { 'custom message' }
|
29
|
+
|
30
|
+
it { expect(subject.wrapped_exception).to be_nil }
|
31
|
+
it { expect(subject.response).to be_nil }
|
32
|
+
it { expect(subject.message).to eq('custom message') }
|
33
|
+
it { expect(subject.inspect).to eq('#<Faraday::ClientError #<Faraday::ClientError: custom message>>') }
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'with anything else #to_s' do
|
37
|
+
let(:exception) { %w[error1 error2] }
|
38
|
+
|
39
|
+
it { expect(subject.wrapped_exception).to be_nil }
|
40
|
+
it { expect(subject.response).to be_nil }
|
41
|
+
it { expect(subject.message).to eq('["error1", "error2"]') }
|
42
|
+
it { expect(subject.inspect).to eq('#<Faraday::ClientError #<Faraday::ClientError: ["error1", "error2"]>>') }
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'maintains backward-compatibility until 1.0' do
|
46
|
+
it 'does not raise an error for error-namespaced classes but prints an error message' do
|
47
|
+
error_message, error = with_warn_squelching { Faraday::Error::ClientError.new('foo') }
|
48
|
+
|
49
|
+
expect(error).to be_a Faraday::ClientError
|
50
|
+
expect(error_message).to match(
|
51
|
+
Regexp.new(
|
52
|
+
'NOTE: Faraday::Error::ClientError.new is deprecated; '\
|
53
|
+
'use Faraday::ClientError.new instead. It will be removed in or after version 1.0'
|
54
|
+
)
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'does not raise an error for inherited error-namespaced classes but prints an error message' do
|
59
|
+
error_message, = with_warn_squelching { Class.new(Faraday::Error::ClientError) }
|
60
|
+
|
61
|
+
expect(error_message).to match(
|
62
|
+
Regexp.new(
|
63
|
+
'NOTE: Inheriting Faraday::Error::ClientError is deprecated; '\
|
64
|
+
'use Faraday::ClientError instead. It will be removed in or after version 1.0'
|
65
|
+
)
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'allows backward-compatible class to be subclassed' do
|
70
|
+
expect {
|
71
|
+
with_warn_squelching { Class.new(Faraday::Error::ClientError) }
|
72
|
+
}.not_to raise_error
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'allows rescuing of a current error with a deprecated error' do
|
76
|
+
expect { raise Faraday::ClientError, nil }.to raise_error(Faraday::Error::ClientError)
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'allows rescuing of a current error with a current error' do
|
80
|
+
expect { raise Faraday::ClientError, nil }.to raise_error(Faraday::ClientError)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'allows rescuing of a deprecated error with a deprecated error' do
|
84
|
+
expect { raise Faraday::Error::ClientError, nil }.to raise_error(Faraday::Error::ClientError)
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'allows rescuing of a deprecated error with a current error' do
|
88
|
+
expect { raise Faraday::Error::ClientError, nil }.to raise_error(Faraday::ClientError)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def with_warn_squelching
|
93
|
+
stderr_catcher = StringIO.new
|
94
|
+
original_stderr = $stderr
|
95
|
+
$stderr = stderr_catcher
|
96
|
+
result = yield if block_given?
|
97
|
+
[stderr_catcher.tap(&:rewind).string, result]
|
98
|
+
ensure
|
99
|
+
$stderr = original_stderr
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Faraday::Response::RaiseError do
|
4
|
+
let(:conn) do
|
5
|
+
Faraday.new do |b|
|
6
|
+
b.response :raise_error
|
7
|
+
b.adapter :test do |stub|
|
8
|
+
stub.get('ok') { [200, { 'Content-Type' => 'text/html' }, '<body></body>'] }
|
9
|
+
stub.get('bad-request') { [400, { 'X-Reason' => 'because' }, 'keep looking'] }
|
10
|
+
stub.get('unauthorized') { [401, { 'X-Reason' => 'because' }, 'keep looking'] }
|
11
|
+
stub.get('forbidden') { [403, { 'X-Reason' => 'because' }, 'keep looking'] }
|
12
|
+
stub.get('not-found') { [404, { 'X-Reason' => 'because' }, 'keep looking'] }
|
13
|
+
stub.get('proxy-error') { [407, { 'X-Reason' => 'because' }, 'keep looking'] }
|
14
|
+
stub.get('conflict') { [409, { 'X-Reason' => 'because' }, 'keep looking'] }
|
15
|
+
stub.get('unprocessable-entity') { [422, { 'X-Reason' => 'because' }, 'keep looking'] }
|
16
|
+
stub.get('4xx') { [499, { 'X-Reason' => 'because' }, 'keep looking'] }
|
17
|
+
stub.get('nil-status') { [nil, { 'X-Reason' => 'bailout' }, 'fail'] }
|
18
|
+
stub.get('server-error') { [500, { 'X-Error' => 'bailout' }, 'fail'] }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'raises no exception for 200 responses' do
|
24
|
+
expect { conn.get('ok') }.not_to raise_error
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'raises Faraday::ClientError for 400 responses' do
|
28
|
+
expect { conn.get('bad-request') }.to raise_error(Faraday::ClientError) do |ex|
|
29
|
+
expect(ex.message).to eq('the server responded with status 400')
|
30
|
+
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'raises Faraday::ClientError for 401 responses' do
|
35
|
+
expect { conn.get('unauthorized') }.to raise_error(Faraday::ClientError) do |ex|
|
36
|
+
expect(ex.message).to eq('the server responded with status 401')
|
37
|
+
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'raises Faraday::ClientError for 403 responses' do
|
42
|
+
expect { conn.get('forbidden') }.to raise_error(Faraday::ClientError) do |ex|
|
43
|
+
expect(ex.message).to eq('the server responded with status 403')
|
44
|
+
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'raises Faraday::ResourceNotFound for 404 responses' do
|
49
|
+
expect { conn.get('not-found') }.to raise_error(Faraday::ResourceNotFound) do |ex|
|
50
|
+
expect(ex.message).to eq('the server responded with status 404')
|
51
|
+
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'raises Faraday::ConnectionFailed for 407 responses' do
|
56
|
+
expect { conn.get('proxy-error') }.to raise_error(Faraday::ConnectionFailed) do |ex|
|
57
|
+
expect(ex.message).to eq('407 "Proxy Authentication Required "')
|
58
|
+
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'raises Faraday::ClientError for 409 responses' do
|
63
|
+
expect { conn.get('conflict') }.to raise_error(Faraday::ClientError) do |ex|
|
64
|
+
expect(ex.message).to eq('the server responded with status 409')
|
65
|
+
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'raises Faraday::ClientError for 422 responses' do
|
70
|
+
expect { conn.get('unprocessable-entity') }.to raise_error(Faraday::ClientError) do |ex|
|
71
|
+
expect(ex.message).to eq('the server responded with status 422')
|
72
|
+
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'raises Faraday::NilStatusError for nil status in response' do
|
77
|
+
expect { conn.get('nil-status') }.to raise_error(Faraday::NilStatusError) do |ex|
|
78
|
+
expect(ex.message).to eq('http status could not be derived from the server response')
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'raises Faraday::ClientError for other 4xx responses' do
|
83
|
+
expect { conn.get('4xx') }.to raise_error(Faraday::ClientError) do |ex|
|
84
|
+
expect(ex.message).to eq('the server responded with status 499')
|
85
|
+
expect(ex.response[:headers]['X-Reason']).to eq('because')
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'raises Faraday::ClientError for 500 responses' do
|
90
|
+
expect { conn.get('server-error') }.to raise_error(Faraday::ClientError) do |ex|
|
91
|
+
expect(ex.message).to eq('the server responded with status 500')
|
92
|
+
expect(ex.response[:headers]['X-Error']).to eq('bailout')
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|