faraday 0.15.2 → 1.10.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +380 -0
  3. data/LICENSE.md +1 -1
  4. data/README.md +17 -345
  5. data/Rakefile +7 -0
  6. data/examples/client_spec.rb +97 -0
  7. data/examples/client_test.rb +118 -0
  8. data/lib/faraday/adapter/test.rb +118 -69
  9. data/lib/faraday/adapter/typhoeus.rb +4 -1
  10. data/lib/faraday/adapter.rb +72 -22
  11. data/lib/faraday/adapter_registry.rb +30 -0
  12. data/lib/faraday/autoload.rb +39 -36
  13. data/lib/faraday/connection.rb +343 -185
  14. data/lib/faraday/dependency_loader.rb +39 -0
  15. data/lib/faraday/deprecate.rb +110 -0
  16. data/lib/faraday/encoders/flat_params_encoder.rb +105 -0
  17. data/lib/faraday/encoders/nested_params_encoder.rb +176 -0
  18. data/lib/faraday/error.rb +118 -38
  19. data/lib/faraday/logging/formatter.rb +105 -0
  20. data/lib/faraday/methods.rb +6 -0
  21. data/lib/faraday/middleware.rb +19 -25
  22. data/lib/faraday/middleware_registry.rb +129 -0
  23. data/lib/faraday/options/connection_options.rb +22 -0
  24. data/lib/faraday/options/env.rb +181 -0
  25. data/lib/faraday/options/proxy_options.rb +32 -0
  26. data/lib/faraday/options/request_options.rb +22 -0
  27. data/lib/faraday/options/ssl_options.rb +59 -0
  28. data/lib/faraday/options.rb +39 -194
  29. data/lib/faraday/parameters.rb +4 -197
  30. data/lib/faraday/rack_builder.rb +77 -65
  31. data/lib/faraday/request/authorization.rb +51 -30
  32. data/lib/faraday/request/basic_authentication.rb +14 -7
  33. data/lib/faraday/request/instrumentation.rb +45 -27
  34. data/lib/faraday/request/json.rb +55 -0
  35. data/lib/faraday/request/token_authentication.rb +15 -10
  36. data/lib/faraday/request/url_encoded.rb +43 -23
  37. data/lib/faraday/request.rb +92 -32
  38. data/lib/faraday/response/json.rb +54 -0
  39. data/lib/faraday/response/logger.rb +20 -69
  40. data/lib/faraday/response/raise_error.rb +49 -14
  41. data/lib/faraday/response.rb +29 -23
  42. data/lib/faraday/utils/headers.rb +139 -0
  43. data/lib/faraday/utils/params_hash.rb +61 -0
  44. data/lib/faraday/utils.rb +38 -247
  45. data/lib/faraday/version.rb +5 -0
  46. data/lib/faraday.rb +134 -189
  47. data/spec/external_adapters/faraday_specs_setup.rb +14 -0
  48. data/spec/faraday/adapter/em_http_spec.rb +49 -0
  49. data/spec/faraday/adapter/em_synchrony_spec.rb +18 -0
  50. data/spec/faraday/adapter/excon_spec.rb +49 -0
  51. data/spec/faraday/adapter/httpclient_spec.rb +73 -0
  52. data/spec/faraday/adapter/net_http_spec.rb +64 -0
  53. data/spec/faraday/adapter/patron_spec.rb +18 -0
  54. data/spec/faraday/adapter/rack_spec.rb +8 -0
  55. data/spec/faraday/adapter/test_spec.rb +377 -0
  56. data/spec/faraday/adapter/typhoeus_spec.rb +7 -0
  57. data/spec/faraday/adapter_registry_spec.rb +28 -0
  58. data/spec/faraday/adapter_spec.rb +55 -0
  59. data/spec/faraday/composite_read_io_spec.rb +80 -0
  60. data/spec/faraday/connection_spec.rb +736 -0
  61. data/spec/faraday/deprecate_spec.rb +147 -0
  62. data/spec/faraday/error_spec.rb +60 -0
  63. data/spec/faraday/middleware_spec.rb +52 -0
  64. data/spec/faraday/options/env_spec.rb +70 -0
  65. data/spec/faraday/options/options_spec.rb +297 -0
  66. data/spec/faraday/options/proxy_options_spec.rb +44 -0
  67. data/spec/faraday/options/request_options_spec.rb +19 -0
  68. data/spec/faraday/params_encoders/flat_spec.rb +42 -0
  69. data/spec/faraday/params_encoders/nested_spec.rb +142 -0
  70. data/spec/faraday/rack_builder_spec.rb +345 -0
  71. data/spec/faraday/request/authorization_spec.rb +96 -0
  72. data/spec/faraday/request/instrumentation_spec.rb +76 -0
  73. data/spec/faraday/request/json_spec.rb +111 -0
  74. data/spec/faraday/request/url_encoded_spec.rb +83 -0
  75. data/spec/faraday/request_spec.rb +120 -0
  76. data/spec/faraday/response/json_spec.rb +119 -0
  77. data/spec/faraday/response/logger_spec.rb +220 -0
  78. data/spec/faraday/response/middleware_spec.rb +68 -0
  79. data/spec/faraday/response/raise_error_spec.rb +169 -0
  80. data/spec/faraday/response_spec.rb +75 -0
  81. data/spec/faraday/utils/headers_spec.rb +82 -0
  82. data/spec/faraday/utils_spec.rb +56 -0
  83. data/spec/faraday_spec.rb +37 -0
  84. data/spec/spec_helper.rb +134 -0
  85. data/spec/support/disabling_stub.rb +14 -0
  86. data/spec/support/fake_safe_buffer.rb +15 -0
  87. data/spec/support/helper_methods.rb +133 -0
  88. data/spec/support/shared_examples/adapter.rb +105 -0
  89. data/spec/support/shared_examples/params_encoder.rb +18 -0
  90. data/spec/support/shared_examples/request_method.rb +262 -0
  91. data/spec/support/streaming_response_checker.rb +35 -0
  92. data/spec/support/webmock_rack_app.rb +68 -0
  93. metadata +224 -29
  94. data/lib/faraday/adapter/em_http.rb +0 -243
  95. data/lib/faraday/adapter/em_http_ssl_patch.rb +0 -56
  96. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +0 -66
  97. data/lib/faraday/adapter/em_synchrony.rb +0 -106
  98. data/lib/faraday/adapter/excon.rb +0 -82
  99. data/lib/faraday/adapter/httpclient.rb +0 -128
  100. data/lib/faraday/adapter/net_http.rb +0 -147
  101. data/lib/faraday/adapter/net_http_persistent.rb +0 -66
  102. data/lib/faraday/adapter/patron.rb +0 -95
  103. data/lib/faraday/adapter/rack.rb +0 -58
  104. data/lib/faraday/request/multipart.rb +0 -68
  105. data/lib/faraday/request/retry.rb +0 -211
  106. data/lib/faraday/upload_io.rb +0 -67
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ruby2_keywords'
4
+
5
+ module Faraday
6
+ # DependencyLoader helps Faraday adapters and middleware load dependencies.
7
+ module DependencyLoader
8
+ attr_reader :load_error
9
+
10
+ # Executes a block which should try to require and reference dependent
11
+ # libraries
12
+ def dependency(lib = nil)
13
+ lib ? require(lib) : yield
14
+ rescue LoadError, NameError => e
15
+ self.load_error = e
16
+ end
17
+
18
+ ruby2_keywords def new(*)
19
+ unless loaded?
20
+ raise "missing dependency for #{self}: #{load_error.message}"
21
+ end
22
+
23
+ super
24
+ end
25
+
26
+ def loaded?
27
+ load_error.nil?
28
+ end
29
+
30
+ def inherited(subclass)
31
+ super
32
+ subclass.send(:load_error=, load_error)
33
+ end
34
+
35
+ private
36
+
37
+ attr_writer :load_error
38
+ end
39
+ end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Faraday
4
+ # @param new_klass [Class] new Klass to use
5
+ #
6
+ # @return [Class] A modified version of new_klass that warns on
7
+ # usage about deprecation.
8
+ # @see Faraday::Deprecate
9
+ module DeprecatedClass
10
+ def self.proxy_class(origclass, ver = '1.0')
11
+ proxy = Class.new(origclass) do
12
+ const_set('ORIG_CLASS', origclass)
13
+
14
+ class << self
15
+ extend Faraday::Deprecate
16
+
17
+ def ===(other)
18
+ (superclass == const_get('ORIG_CLASS') && other.is_a?(superclass)) || super
19
+ end
20
+ end
21
+ end
22
+ proxy.singleton_class.send(:deprecate, :new, "#{origclass}.new", ver)
23
+ proxy.singleton_class.send(:deprecate, :inherited, origclass.name, ver)
24
+ proxy
25
+ end
26
+ end
27
+
28
+ # Deprecation using semver instead of date, based on Gem::Deprecate
29
+ # Provides a single method +deprecate+ to be used to declare when
30
+ # something is going away.
31
+ #
32
+ # class Legacy
33
+ # def self.klass_method
34
+ # # ...
35
+ # end
36
+ #
37
+ # def instance_method
38
+ # # ...
39
+ # end
40
+ #
41
+ # extend Faraday::Deprecate
42
+ # deprecate :instance_method, "X.z", '1.0'
43
+ #
44
+ # class << self
45
+ # extend Faraday::Deprecate
46
+ # deprecate :klass_method, :none, '1.0'
47
+ # end
48
+ # end
49
+ module Deprecate
50
+ def self.skip # :nodoc:
51
+ @skip ||= begin
52
+ case ENV['FARADAY_DEPRECATE'].to_s.downcase
53
+ when '1', 'warn' then :warn
54
+ else :skip
55
+ end
56
+ end
57
+ @skip == :skip
58
+ end
59
+
60
+ def self.skip=(value) # :nodoc:
61
+ @skip = value ? :skip : :warn
62
+ end
63
+
64
+ # Temporarily turn off warnings. Intended for tests only.
65
+ def skip_during
66
+ original = Faraday::Deprecate.skip
67
+ Faraday::Deprecate.skip = true
68
+ yield
69
+ ensure
70
+ Faraday::Deprecate.skip = original
71
+ end
72
+
73
+ # Simple deprecation method that deprecates +name+ by wrapping it up
74
+ # in a dummy method. It warns on each call to the dummy method
75
+ # telling the user of +repl+ (unless +repl+ is :none) and the
76
+ # semver that it is planned to go away.
77
+ # @param name [Symbol] the method symbol to deprecate
78
+ # @param repl [#to_s, :none] the replacement to use, when `:none` it will
79
+ # alert the user that no replacement is present.
80
+ # @param ver [String] the semver the method will be removed.
81
+ def deprecate(name, repl, ver, custom_message = nil)
82
+ class_eval do
83
+ gem_ver = Gem::Version.new(ver)
84
+ old = "_deprecated_#{name}"
85
+ alias_method old, name
86
+ define_method name do |*args, &block|
87
+ mod = is_a? Module
88
+ target = mod ? "#{self}." : "#{self.class}#"
89
+ target_message = if name == :inherited
90
+ "Inheriting #{self}"
91
+ else
92
+ "#{target}#{name}"
93
+ end
94
+
95
+ msg = [
96
+ "NOTE: #{target_message} is deprecated",
97
+ repl == :none ? ' with no replacement' : "; use #{repl} instead. ",
98
+ "It will be removed in or after version #{gem_ver} ",
99
+ custom_message,
100
+ "\n#{target}#{name} called from #{Gem.location_of_caller.join(':')}"
101
+ ]
102
+ warn "#{msg.join}." unless Faraday::Deprecate.skip
103
+ send old, *args, &block
104
+ end
105
+ end
106
+ end
107
+
108
+ module_function :deprecate, :skip_during
109
+ end
110
+ end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Faraday
4
+ # FlatParamsEncoder manages URI params as a flat hash. Any Array values repeat
5
+ # the parameter multiple times.
6
+ module FlatParamsEncoder
7
+ class << self
8
+ extend Forwardable
9
+ def_delegators :'Faraday::Utils', :escape, :unescape
10
+ end
11
+
12
+ # Encode converts the given param into a URI querystring. Keys and values
13
+ # will converted to strings and appropriately escaped for the URI.
14
+ #
15
+ # @param params [Hash] query arguments to convert.
16
+ #
17
+ # @example
18
+ #
19
+ # encode({a: %w[one two three], b: true, c: "C"})
20
+ # # => 'a=one&a=two&a=three&b=true&c=C'
21
+ #
22
+ # @return [String] the URI querystring (without the leading '?')
23
+ def self.encode(params)
24
+ return nil if params.nil?
25
+
26
+ unless params.is_a?(Array)
27
+ unless params.respond_to?(:to_hash)
28
+ raise TypeError,
29
+ "Can't convert #{params.class} into Hash."
30
+ end
31
+ params = params.to_hash
32
+ params = params.map do |key, value|
33
+ key = key.to_s if key.is_a?(Symbol)
34
+ [key, value]
35
+ end
36
+
37
+ # Only to be used for non-Array inputs. Arrays should preserve order.
38
+ params.sort! if @sort_params
39
+ end
40
+
41
+ # The params have form [['key1', 'value1'], ['key2', 'value2']].
42
+ buffer = +''
43
+ params.each do |key, value|
44
+ encoded_key = escape(key)
45
+ if value.nil?
46
+ buffer << "#{encoded_key}&"
47
+ elsif value.is_a?(Array)
48
+ if value.empty?
49
+ buffer << "#{encoded_key}=&"
50
+ else
51
+ value.each do |sub_value|
52
+ encoded_value = escape(sub_value)
53
+ buffer << "#{encoded_key}=#{encoded_value}&"
54
+ end
55
+ end
56
+ else
57
+ encoded_value = escape(value)
58
+ buffer << "#{encoded_key}=#{encoded_value}&"
59
+ end
60
+ end
61
+ buffer.chop
62
+ end
63
+
64
+ # Decode converts the given URI querystring into a hash.
65
+ #
66
+ # @param query [String] query arguments to parse.
67
+ #
68
+ # @example
69
+ #
70
+ # decode('a=one&a=two&a=three&b=true&c=C')
71
+ # # => {"a"=>["one", "two", "three"], "b"=>"true", "c"=>"C"}
72
+ #
73
+ # @return [Hash] parsed keys and value strings from the querystring.
74
+ def self.decode(query)
75
+ return nil if query.nil?
76
+
77
+ empty_accumulator = {}
78
+
79
+ split_query = (query.split('&').map do |pair|
80
+ pair.split('=', 2) if pair && !pair.empty?
81
+ end).compact
82
+ split_query.each_with_object(empty_accumulator.dup) do |pair, accu|
83
+ pair[0] = unescape(pair[0])
84
+ pair[1] = true if pair[1].nil?
85
+ if pair[1].respond_to?(:to_str)
86
+ pair[1] = unescape(pair[1].to_str.tr('+', ' '))
87
+ end
88
+ if accu[pair[0]].is_a?(Array)
89
+ accu[pair[0]] << pair[1]
90
+ elsif accu[pair[0]]
91
+ accu[pair[0]] = [accu[pair[0]], pair[1]]
92
+ else
93
+ accu[pair[0]] = pair[1]
94
+ end
95
+ end
96
+ end
97
+
98
+ class << self
99
+ attr_accessor :sort_params
100
+ end
101
+
102
+ # Useful default for OAuth and caching.
103
+ @sort_params = true
104
+ end
105
+ end
@@ -0,0 +1,176 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Faraday
4
+ # Sub-module for encoding parameters into query-string.
5
+ module EncodeMethods
6
+ # @param params [nil, Array, #to_hash] parameters to be encoded
7
+ #
8
+ # @return [String] the encoded params
9
+ #
10
+ # @raise [TypeError] if params can not be converted to a Hash
11
+ def encode(params)
12
+ return nil if params.nil?
13
+
14
+ unless params.is_a?(Array)
15
+ unless params.respond_to?(:to_hash)
16
+ raise TypeError, "Can't convert #{params.class} into Hash."
17
+ end
18
+
19
+ params = params.to_hash
20
+ params = params.map do |key, value|
21
+ key = key.to_s if key.is_a?(Symbol)
22
+ [key, value]
23
+ end
24
+
25
+ # Only to be used for non-Array inputs. Arrays should preserve order.
26
+ params.sort! if @sort_params
27
+ end
28
+
29
+ # The params have form [['key1', 'value1'], ['key2', 'value2']].
30
+ buffer = +''
31
+ params.each do |parent, value|
32
+ encoded_parent = escape(parent)
33
+ buffer << "#{encode_pair(encoded_parent, value)}&"
34
+ end
35
+ buffer.chop
36
+ end
37
+
38
+ protected
39
+
40
+ def encode_pair(parent, value)
41
+ if value.is_a?(Hash)
42
+ encode_hash(parent, value)
43
+ elsif value.is_a?(Array)
44
+ encode_array(parent, value)
45
+ elsif value.nil?
46
+ parent
47
+ else
48
+ encoded_value = escape(value)
49
+ "#{parent}=#{encoded_value}"
50
+ end
51
+ end
52
+
53
+ def encode_hash(parent, value)
54
+ value = value.map { |key, val| [escape(key), val] }.sort
55
+
56
+ buffer = +''
57
+ value.each do |key, val|
58
+ new_parent = "#{parent}%5B#{key}%5D"
59
+ buffer << "#{encode_pair(new_parent, val)}&"
60
+ end
61
+ buffer.chop
62
+ end
63
+
64
+ def encode_array(parent, value)
65
+ new_parent = "#{parent}%5B%5D"
66
+ return new_parent if value.empty?
67
+
68
+ buffer = +''
69
+ value.each { |val| buffer << "#{encode_pair(new_parent, val)}&" }
70
+ buffer.chop
71
+ end
72
+ end
73
+
74
+ # Sub-module for decoding query-string into parameters.
75
+ module DecodeMethods
76
+ # @param query [nil, String]
77
+ #
78
+ # @return [Array<Array, String>] the decoded params
79
+ #
80
+ # @raise [TypeError] if the nesting is incorrect
81
+ def decode(query)
82
+ return nil if query.nil?
83
+
84
+ params = {}
85
+ query.split('&').each do |pair|
86
+ next if pair.empty?
87
+
88
+ key, value = pair.split('=', 2)
89
+ key = unescape(key)
90
+ value = unescape(value.tr('+', ' ')) if value
91
+ decode_pair(key, value, params)
92
+ end
93
+
94
+ dehash(params, 0)
95
+ end
96
+
97
+ protected
98
+
99
+ SUBKEYS_REGEX = /[^\[\]]+(?:\]?\[\])?/.freeze
100
+
101
+ def decode_pair(key, value, context)
102
+ subkeys = key.scan(SUBKEYS_REGEX)
103
+ subkeys.each_with_index do |subkey, i|
104
+ is_array = subkey =~ /[\[\]]+\Z/
105
+ subkey = $` if is_array
106
+ last_subkey = i == subkeys.length - 1
107
+
108
+ context = prepare_context(context, subkey, is_array, last_subkey)
109
+ add_to_context(is_array, context, value, subkey) if last_subkey
110
+ end
111
+ end
112
+
113
+ def prepare_context(context, subkey, is_array, last_subkey)
114
+ if !last_subkey || is_array
115
+ context = new_context(subkey, is_array, context)
116
+ end
117
+ if context.is_a?(Array) && !is_array
118
+ context = match_context(context, subkey)
119
+ end
120
+ context
121
+ end
122
+
123
+ def new_context(subkey, is_array, context)
124
+ value_type = is_array ? Array : Hash
125
+ if context[subkey] && !context[subkey].is_a?(value_type)
126
+ raise TypeError, "expected #{value_type.name} " \
127
+ "(got #{context[subkey].class.name}) for param `#{subkey}'"
128
+ end
129
+
130
+ context[subkey] ||= value_type.new
131
+ end
132
+
133
+ def match_context(context, subkey)
134
+ context << {} if !context.last.is_a?(Hash) || context.last.key?(subkey)
135
+ context.last
136
+ end
137
+
138
+ def add_to_context(is_array, context, value, subkey)
139
+ is_array ? context << value : context[subkey] = value
140
+ end
141
+
142
+ # Internal: convert a nested hash with purely numeric keys into an array.
143
+ # FIXME: this is not compatible with Rack::Utils.parse_nested_query
144
+ # @!visibility private
145
+ def dehash(hash, depth)
146
+ hash.each do |key, value|
147
+ hash[key] = dehash(value, depth + 1) if value.is_a?(Hash)
148
+ end
149
+
150
+ if depth.positive? && !hash.empty? && hash.keys.all? { |k| k =~ /^\d+$/ }
151
+ hash.sort.map(&:last)
152
+ else
153
+ hash
154
+ end
155
+ end
156
+ end
157
+
158
+ # This is the default encoder for Faraday requests.
159
+ # Using this encoder, parameters will be encoded respecting their structure,
160
+ # so you can send objects such as Arrays or Hashes as parameters
161
+ # for your requests.
162
+ module NestedParamsEncoder
163
+ class << self
164
+ attr_accessor :sort_params
165
+
166
+ extend Forwardable
167
+ def_delegators :'Faraday::Utils', :escape, :unescape
168
+ end
169
+
170
+ # Useful default for OAuth and caching.
171
+ @sort_params = true
172
+
173
+ extend EncodeMethods
174
+ extend DecodeMethods
175
+ end
176
+ end
data/lib/faraday/error.rb CHANGED
@@ -1,22 +1,15 @@
1
- module Faraday
2
- class Error < StandardError; end
1
+ # frozen_string_literal: true
3
2
 
4
- class ClientError < Error
3
+ # Faraday namespace.
4
+ module Faraday
5
+ # Faraday error base class.
6
+ class Error < StandardError
5
7
  attr_reader :response, :wrapped_exception
6
8
 
7
- def initialize(ex, response = nil)
8
- @wrapped_exception = nil
9
- @response = response
10
-
11
- if ex.respond_to?(:backtrace)
12
- super(ex.message)
13
- @wrapped_exception = ex
14
- elsif ex.respond_to?(:each_key)
15
- super("the server responded with status #{ex[:status]}")
16
- @response = ex
17
- else
18
- super(ex.to_s)
19
- end
9
+ def initialize(exc, response = nil)
10
+ @wrapped_exception = nil unless defined?(@wrapped_exception)
11
+ @response = nil unless defined?(@response)
12
+ super(exc_msg_and_response!(exc, response))
20
13
  end
21
14
 
22
15
  def backtrace
@@ -28,39 +21,126 @@ module Faraday
28
21
  end
29
22
 
30
23
  def inspect
31
- inner = ''
32
- if @wrapped_exception
33
- inner << " wrapped=#{@wrapped_exception.inspect}"
34
- end
35
- if @response
36
- inner << " response=#{@response.inspect}"
37
- end
38
- if inner.empty?
39
- inner << " #{super}"
40
- end
24
+ inner = +''
25
+ inner << " wrapped=#{@wrapped_exception.inspect}" if @wrapped_exception
26
+ inner << " response=#{@response.inspect}" if @response
27
+ inner << " #{super}" if inner.empty?
41
28
  %(#<#{self.class}#{inner}>)
42
29
  end
43
- end
44
30
 
45
- class ConnectionFailed < ClientError; end
46
- class ResourceNotFound < ClientError; end
47
- class ParsingError < ClientError; end
31
+ def response_status
32
+ @response[:status] if @response
33
+ end
34
+
35
+ def response_headers
36
+ @response[:headers] if @response
37
+ end
38
+
39
+ def response_body
40
+ @response[:body] if @response
41
+ end
42
+
43
+ protected
44
+
45
+ # Pulls out potential parent exception and response hash, storing them in
46
+ # instance variables.
47
+ # exc - Either an Exception, a string message, or a response hash.
48
+ # response - Hash
49
+ # :status - Optional integer HTTP response status
50
+ # :headers - String key/value hash of HTTP response header
51
+ # values.
52
+ # :body - Optional string HTTP response body.
53
+ # :request - Hash
54
+ # :method - Symbol with the request HTTP method.
55
+ # :url_path - String with the url path requested.
56
+ # :params - String key/value hash of query params
57
+ # present in the request.
58
+ # :headers - String key/value hash of HTTP request
59
+ # header values.
60
+ # :body - String HTTP request body.
61
+ #
62
+ # If a subclass has to call this, then it should pass a string message
63
+ # to `super`. See NilStatusError.
64
+ def exc_msg_and_response!(exc, response = nil)
65
+ if @response.nil? && @wrapped_exception.nil?
66
+ @wrapped_exception, msg, @response = exc_msg_and_response(exc, response)
67
+ return msg
68
+ end
69
+
70
+ exc.to_s
71
+ end
48
72
 
49
- class TimeoutError < ClientError
50
- def initialize(ex = nil)
51
- super(ex || "timeout")
73
+ # Pulls out potential parent exception and response hash.
74
+ def exc_msg_and_response(exc, response = nil)
75
+ return [exc, exc.message, response] if exc.respond_to?(:backtrace)
76
+
77
+ return [nil, "the server responded with status #{exc[:status]}", exc] \
78
+ if exc.respond_to?(:each_key)
79
+
80
+ [nil, exc.to_s, response]
52
81
  end
53
82
  end
54
83
 
55
- class SSLError < ClientError
84
+ # Faraday client error class. Represents 4xx status responses.
85
+ class ClientError < Error
56
86
  end
57
87
 
58
- class RetriableResponse < ClientError; end
88
+ # Raised by Faraday::Response::RaiseError in case of a 400 response.
89
+ class BadRequestError < ClientError
90
+ end
91
+
92
+ # Raised by Faraday::Response::RaiseError in case of a 401 response.
93
+ class UnauthorizedError < ClientError
94
+ end
95
+
96
+ # Raised by Faraday::Response::RaiseError in case of a 403 response.
97
+ class ForbiddenError < ClientError
98
+ end
99
+
100
+ # Raised by Faraday::Response::RaiseError in case of a 404 response.
101
+ class ResourceNotFound < ClientError
102
+ end
103
+
104
+ # Raised by Faraday::Response::RaiseError in case of a 407 response.
105
+ class ProxyAuthError < ClientError
106
+ end
59
107
 
60
- [:ClientError, :ConnectionFailed, :ResourceNotFound,
61
- :ParsingError, :TimeoutError, :SSLError, :RetriableResponse].each do |const|
62
- Error.const_set(const, Faraday.const_get(const))
108
+ # Raised by Faraday::Response::RaiseError in case of a 409 response.
109
+ class ConflictError < ClientError
63
110
  end
64
111
 
112
+ # Raised by Faraday::Response::RaiseError in case of a 422 response.
113
+ class UnprocessableEntityError < ClientError
114
+ end
115
+
116
+ # Faraday server error class. Represents 5xx status responses.
117
+ class ServerError < Error
118
+ end
65
119
 
120
+ # A unified client error for timeouts.
121
+ class TimeoutError < ServerError
122
+ def initialize(exc = 'timeout', response = nil)
123
+ super(exc, response)
124
+ end
125
+ end
126
+
127
+ # Raised by Faraday::Response::RaiseError in case of a nil status in response.
128
+ class NilStatusError < ServerError
129
+ def initialize(exc, response = nil)
130
+ exc_msg_and_response!(exc, response)
131
+ super('http status could not be derived from the server response')
132
+ end
133
+ end
134
+
135
+ # A unified error for failed connections.
136
+ class ConnectionFailed < Error
137
+ end
138
+
139
+ # A unified client error for SSL errors.
140
+ class SSLError < Error
141
+ end
142
+
143
+ # Raised by FaradayMiddleware::ResponseMiddleware
144
+ class ParsingError < Error
145
+ end
66
146
  end