faraday 0.17.6 → 1.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +156 -8
  3. data/LICENSE.md +1 -1
  4. data/README.md +16 -358
  5. data/Rakefile +1 -7
  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 +7 -6
  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 +28 -40
  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 +36 -191
  29. data/lib/faraday/parameters.rb +4 -197
  30. data/lib/faraday/rack_builder.rb +76 -64
  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 +82 -44
  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 -18
  41. data/lib/faraday/response.rb +26 -20
  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 -188
  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 +17 -17
  62. data/spec/faraday/error_spec.rb +12 -54
  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 +78 -15
  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 +65 -36
  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 +210 -56
  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 -153
  101. data/lib/faraday/adapter/net_http_persistent.rb +0 -68
  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 -213
  106. data/lib/faraday/upload_io.rb +0 -77
  107. data/test/adapters/default_test.rb +0 -14
  108. data/test/adapters/em_http_test.rb +0 -30
  109. data/test/adapters/em_synchrony_test.rb +0 -32
  110. data/test/adapters/excon_test.rb +0 -30
  111. data/test/adapters/httpclient_test.rb +0 -34
  112. data/test/adapters/integration.rb +0 -263
  113. data/test/adapters/logger_test.rb +0 -136
  114. data/test/adapters/net_http_persistent_test.rb +0 -114
  115. data/test/adapters/net_http_test.rb +0 -79
  116. data/test/adapters/patron_test.rb +0 -40
  117. data/test/adapters/rack_test.rb +0 -38
  118. data/test/adapters/test_middleware_test.rb +0 -157
  119. data/test/adapters/typhoeus_test.rb +0 -38
  120. data/test/authentication_middleware_test.rb +0 -65
  121. data/test/composite_read_io_test.rb +0 -109
  122. data/test/connection_test.rb +0 -738
  123. data/test/env_test.rb +0 -268
  124. data/test/helper.rb +0 -75
  125. data/test/live_server.rb +0 -67
  126. data/test/middleware/instrumentation_test.rb +0 -88
  127. data/test/middleware/retry_test.rb +0 -282
  128. data/test/middleware_stack_test.rb +0 -260
  129. data/test/multibyte.txt +0 -1
  130. data/test/options_test.rb +0 -333
  131. data/test/parameters_test.rb +0 -157
  132. data/test/request_middleware_test.rb +0 -126
  133. data/test/response_middleware_test.rb +0 -72
  134. data/test/strawberry.rb +0 -2
  135. data/test/utils_test.rb +0 -98
@@ -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
@@ -9,13 +9,13 @@ module Faraday
9
9
  module DeprecatedClass
10
10
  def self.proxy_class(origclass, ver = '1.0')
11
11
  proxy = Class.new(origclass) do
12
- const_set("ORIG_CLASS", origclass)
12
+ const_set('ORIG_CLASS', origclass)
13
13
 
14
14
  class << self
15
15
  extend Faraday::Deprecate
16
16
 
17
17
  def ===(other)
18
- (superclass == const_get("ORIG_CLASS") && other.is_a?(superclass)) || super
18
+ (superclass == const_get('ORIG_CLASS') && other.is_a?(superclass)) || super
19
19
  end
20
20
  end
21
21
  end
@@ -64,7 +64,7 @@ module Faraday
64
64
  # Temporarily turn off warnings. Intended for tests only.
65
65
  def skip_during
66
66
  original = Faraday::Deprecate.skip
67
- Faraday::Deprecate.skip, = true
67
+ Faraday::Deprecate.skip = true
68
68
  yield
69
69
  ensure
70
70
  Faraday::Deprecate.skip = original
@@ -76,9 +76,9 @@ module Faraday
76
76
  # semver that it is planned to go away.
77
77
  # @param name [Symbol] the method symbol to deprecate
78
78
  # @param repl [#to_s, :none] the replacement to use, when `:none` it will
79
- # alert the user that no replacemtent is present.
79
+ # alert the user that no replacement is present.
80
80
  # @param ver [String] the semver the method will be removed.
81
- def deprecate(name, repl, ver)
81
+ def deprecate(name, repl, ver, custom_message = nil)
82
82
  class_eval do
83
83
  gem_ver = Gem::Version.new(ver)
84
84
  old = "_deprecated_#{name}"
@@ -95,7 +95,8 @@ module Faraday
95
95
  msg = [
96
96
  "NOTE: #{target_message} is deprecated",
97
97
  repl == :none ? ' with no replacement' : "; use #{repl} instead. ",
98
- "It will be removed in or after version #{gem_ver}",
98
+ "It will be removed in or after version #{gem_ver} ",
99
+ custom_message,
99
100
  "\n#{target}#{name} called from #{Gem.location_of_caller.join(':')}"
100
101
  ]
101
102
  warn "#{msg.join}." unless Faraday::Deprecate.skip
@@ -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,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'faraday/deprecate'
4
-
5
3
  # Faraday namespace.
6
4
  module Faraday
7
5
  # Faraday error base class.
@@ -23,13 +21,25 @@ module Faraday
23
21
  end
24
22
 
25
23
  def inspect
26
- inner = ''
27
- inner += " wrapped=#{@wrapped_exception.inspect}" if @wrapped_exception
28
- inner += " response=#{@response.inspect}" if @response
29
- inner += " #{super}" if inner.empty?
24
+ inner = +''
25
+ inner << " wrapped=#{@wrapped_exception.inspect}" if @wrapped_exception
26
+ inner << " response=#{@response.inspect}" if @response
27
+ inner << " #{super}" if inner.empty?
30
28
  %(#<#{self.class}#{inner}>)
31
29
  end
32
30
 
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
+
33
43
  protected
34
44
 
35
45
  # Pulls out potential parent exception and response hash, storing them in
@@ -40,6 +50,14 @@ module Faraday
40
50
  # :headers - String key/value hash of HTTP response header
41
51
  # values.
42
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.
43
61
  #
44
62
  # If a subclass has to call this, then it should pass a string message
45
63
  # to `super`. See NilStatusError.
@@ -100,7 +118,7 @@ module Faraday
100
118
  end
101
119
 
102
120
  # A unified client error for timeouts.
103
- class TimeoutError < ClientError
121
+ class TimeoutError < ServerError
104
122
  def initialize(exc = 'timeout', response = nil)
105
123
  super(exc, response)
106
124
  end
@@ -110,49 +128,19 @@ module Faraday
110
128
  class NilStatusError < ServerError
111
129
  def initialize(exc, response = nil)
112
130
  exc_msg_and_response!(exc, response)
113
- @response = unwrap_resp!(@response)
114
131
  super('http status could not be derived from the server response')
115
132
  end
116
-
117
- private
118
-
119
- extend Faraday::Deprecate
120
-
121
- def unwrap_resp(resp)
122
- if inner = (resp.keys.size == 1 && resp[:response])
123
- return unwrap_resp(inner)
124
- end
125
-
126
- resp
127
- end
128
-
129
- alias_method :unwrap_resp!, :unwrap_resp
130
- deprecate('unwrap_resp', nil, '1.0')
131
133
  end
132
134
 
133
135
  # A unified error for failed connections.
134
- class ConnectionFailed < ClientError
136
+ class ConnectionFailed < Error
135
137
  end
136
138
 
137
139
  # A unified client error for SSL errors.
138
- class SSLError < ClientError
140
+ class SSLError < Error
139
141
  end
140
142
 
141
143
  # Raised by FaradayMiddleware::ResponseMiddleware
142
- class ParsingError < ClientError
143
- end
144
-
145
- # Exception used to control the Retry middleware.
146
- #
147
- # @see Faraday::Request::Retry
148
- class RetriableResponse < ClientError
149
- end
150
-
151
- [:ClientError, :ConnectionFailed, :ResourceNotFound,
152
- :ParsingError, :TimeoutError, :SSLError, :RetriableResponse].each do |const|
153
- Error.const_set(
154
- const,
155
- DeprecatedClass.proxy_class(Faraday.const_get(const))
156
- )
144
+ class ParsingError < Error
157
145
  end
158
146
  end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pp'
4
+ module Faraday
5
+ module Logging
6
+ # Serves as an integration point to customize logging
7
+ class Formatter
8
+ extend Forwardable
9
+
10
+ DEFAULT_OPTIONS = { headers: true, bodies: false,
11
+ log_level: :info }.freeze
12
+
13
+ def initialize(logger:, options:)
14
+ @logger = logger
15
+ @filter = []
16
+ @options = DEFAULT_OPTIONS.merge(options)
17
+ end
18
+
19
+ def_delegators :@logger, :debug, :info, :warn, :error, :fatal
20
+
21
+ def request(env)
22
+ request_log = proc do
23
+ "#{env.method.upcase} #{apply_filters(env.url.to_s)}"
24
+ end
25
+ public_send(log_level, 'request', &request_log)
26
+
27
+ log_headers('request', env.request_headers) if log_headers?(:request)
28
+ log_body('request', env[:body]) if env[:body] && log_body?(:request)
29
+ end
30
+
31
+ def response(env)
32
+ status = proc { "Status #{env.status}" }
33
+ public_send(log_level, 'response', &status)
34
+
35
+ log_headers('response', env.response_headers) if log_headers?(:response)
36
+ log_body('response', env[:body]) if env[:body] && log_body?(:response)
37
+ end
38
+
39
+ def filter(filter_word, filter_replacement)
40
+ @filter.push([filter_word, filter_replacement])
41
+ end
42
+
43
+ private
44
+
45
+ def dump_headers(headers)
46
+ headers.map { |k, v| "#{k}: #{v.inspect}" }.join("\n")
47
+ end
48
+
49
+ def dump_body(body)
50
+ if body.respond_to?(:to_str)
51
+ body.to_str
52
+ else
53
+ pretty_inspect(body)
54
+ end
55
+ end
56
+
57
+ def pretty_inspect(body)
58
+ body.pretty_inspect
59
+ end
60
+
61
+ def log_headers?(type)
62
+ case @options[:headers]
63
+ when Hash
64
+ @options[:headers][type]
65
+ else
66
+ @options[:headers]
67
+ end
68
+ end
69
+
70
+ def log_body?(type)
71
+ case @options[:bodies]
72
+ when Hash
73
+ @options[:bodies][type]
74
+ else
75
+ @options[:bodies]
76
+ end
77
+ end
78
+
79
+ def apply_filters(output)
80
+ @filter.each do |pattern, replacement|
81
+ output = output.to_s.gsub(pattern, replacement)
82
+ end
83
+ output
84
+ end
85
+
86
+ def log_level
87
+ unless %i[debug info warn error fatal].include?(@options[:log_level])
88
+ return :info
89
+ end
90
+
91
+ @options[:log_level]
92
+ end
93
+
94
+ def log_headers(type, headers)
95
+ headers_log = proc { apply_filters(dump_headers(headers)) }
96
+ public_send(log_level, type, &headers_log)
97
+ end
98
+
99
+ def log_body(type, body)
100
+ body_log = proc { apply_filters(dump_body(body)) }
101
+ public_send(log_level, type, &body_log)
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Faraday
4
+ METHODS_WITH_QUERY = %w[get head delete trace].freeze
5
+ METHODS_WITH_BODY = %w[post put patch].freeze
6
+ end
@@ -1,37 +1,31 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Faraday
4
+ # Middleware is the basic base class of any Faraday middleware.
2
5
  class Middleware
3
6
  extend MiddlewareRegistry
7
+ extend DependencyLoader
4
8
 
5
- class << self
6
- attr_accessor :load_error
7
- private :load_error=
8
- end
9
-
10
- self.load_error = nil
11
-
12
- # Executes a block which should try to require and reference dependent libraries
13
- def self.dependency(lib = nil)
14
- lib ? require(lib) : yield
15
- rescue LoadError, NameError => error
16
- self.load_error = error
17
- end
9
+ attr_reader :app, :options
18
10
 
19
- def self.new(*)
20
- raise "missing dependency for #{self}: #{load_error.message}" unless loaded?
21
- super
22
- end
23
-
24
- def self.loaded?
25
- load_error.nil?
11
+ def initialize(app = nil, options = {})
12
+ @app = app
13
+ @options = options
26
14
  end
27
15
 
28
- def self.inherited(subclass)
29
- super
30
- subclass.send(:load_error=, self.load_error)
16
+ def call(env)
17
+ on_request(env) if respond_to?(:on_request)
18
+ app.call(env).on_complete do |environment|
19
+ on_complete(environment) if respond_to?(:on_complete)
20
+ end
31
21
  end
32
22
 
33
- def initialize(app = nil)
34
- @app = app
23
+ def close
24
+ if app.respond_to?(:close)
25
+ app.close
26
+ else
27
+ warn "#{app} does not implement \#close!"
28
+ end
35
29
  end
36
30
  end
37
31
  end