faraday 0.9.1 → 2.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +554 -0
  3. data/LICENSE.md +1 -1
  4. data/README.md +32 -197
  5. data/Rakefile +4 -68
  6. data/examples/client_spec.rb +119 -0
  7. data/examples/client_test.rb +144 -0
  8. data/lib/faraday/adapter/test.rb +194 -58
  9. data/lib/faraday/adapter.rb +76 -20
  10. data/lib/faraday/adapter_registry.rb +30 -0
  11. data/lib/faraday/connection.rb +341 -212
  12. data/lib/faraday/encoders/flat_params_encoder.rb +105 -0
  13. data/lib/faraday/encoders/nested_params_encoder.rb +183 -0
  14. data/lib/faraday/error.rb +123 -29
  15. data/lib/faraday/logging/formatter.rb +106 -0
  16. data/lib/faraday/methods.rb +6 -0
  17. data/lib/faraday/middleware.rb +18 -25
  18. data/lib/faraday/middleware_registry.rb +83 -0
  19. data/lib/faraday/options/connection_options.rb +22 -0
  20. data/lib/faraday/options/env.rb +199 -0
  21. data/lib/faraday/options/proxy_options.rb +32 -0
  22. data/lib/faraday/options/request_options.rb +22 -0
  23. data/lib/faraday/options/ssl_options.rb +69 -0
  24. data/lib/faraday/options.rb +63 -195
  25. data/lib/faraday/parameters.rb +4 -180
  26. data/lib/faraday/rack_builder.rb +99 -59
  27. data/lib/faraday/request/authorization.rb +37 -30
  28. data/lib/faraday/request/instrumentation.rb +47 -27
  29. data/lib/faraday/request/json.rb +55 -0
  30. data/lib/faraday/request/url_encoded.rb +48 -24
  31. data/lib/faraday/request.rb +76 -32
  32. data/lib/faraday/response/json.rb +54 -0
  33. data/lib/faraday/response/logger.rb +22 -48
  34. data/lib/faraday/response/raise_error.rb +57 -14
  35. data/lib/faraday/response.rb +32 -35
  36. data/lib/faraday/utils/headers.rb +139 -0
  37. data/lib/faraday/utils/params_hash.rb +61 -0
  38. data/lib/faraday/utils.rb +47 -222
  39. data/lib/faraday/version.rb +5 -0
  40. data/lib/faraday.rb +111 -222
  41. data/spec/external_adapters/faraday_specs_setup.rb +14 -0
  42. data/spec/faraday/adapter/test_spec.rb +413 -0
  43. data/spec/faraday/adapter_registry_spec.rb +28 -0
  44. data/spec/faraday/adapter_spec.rb +55 -0
  45. data/spec/faraday/connection_spec.rb +793 -0
  46. data/spec/faraday/error_spec.rb +60 -0
  47. data/spec/faraday/middleware_registry_spec.rb +31 -0
  48. data/spec/faraday/middleware_spec.rb +52 -0
  49. data/spec/faraday/options/env_spec.rb +76 -0
  50. data/spec/faraday/options/options_spec.rb +297 -0
  51. data/spec/faraday/options/proxy_options_spec.rb +44 -0
  52. data/spec/faraday/options/request_options_spec.rb +19 -0
  53. data/spec/faraday/params_encoders/flat_spec.rb +42 -0
  54. data/spec/faraday/params_encoders/nested_spec.rb +150 -0
  55. data/spec/faraday/rack_builder_spec.rb +317 -0
  56. data/spec/faraday/request/authorization_spec.rb +83 -0
  57. data/spec/faraday/request/instrumentation_spec.rb +74 -0
  58. data/spec/faraday/request/json_spec.rb +111 -0
  59. data/spec/faraday/request/url_encoded_spec.rb +93 -0
  60. data/spec/faraday/request_spec.rb +110 -0
  61. data/spec/faraday/response/json_spec.rb +117 -0
  62. data/spec/faraday/response/logger_spec.rb +220 -0
  63. data/spec/faraday/response/raise_error_spec.rb +172 -0
  64. data/spec/faraday/response_spec.rb +75 -0
  65. data/spec/faraday/utils/headers_spec.rb +82 -0
  66. data/spec/faraday/utils_spec.rb +118 -0
  67. data/spec/faraday_spec.rb +37 -0
  68. data/spec/spec_helper.rb +132 -0
  69. data/spec/support/disabling_stub.rb +14 -0
  70. data/spec/support/fake_safe_buffer.rb +15 -0
  71. data/spec/support/helper_methods.rb +96 -0
  72. data/spec/support/shared_examples/adapter.rb +105 -0
  73. data/spec/support/shared_examples/params_encoder.rb +18 -0
  74. data/spec/support/shared_examples/request_method.rb +263 -0
  75. data/spec/support/streaming_response_checker.rb +35 -0
  76. metadata +81 -109
  77. data/.document +0 -6
  78. data/CONTRIBUTING.md +0 -36
  79. data/Gemfile +0 -25
  80. data/faraday.gemspec +0 -34
  81. data/lib/faraday/adapter/em_http.rb +0 -237
  82. data/lib/faraday/adapter/em_http_ssl_patch.rb +0 -56
  83. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +0 -66
  84. data/lib/faraday/adapter/em_synchrony.rb +0 -92
  85. data/lib/faraday/adapter/excon.rb +0 -80
  86. data/lib/faraday/adapter/httpclient.rb +0 -106
  87. data/lib/faraday/adapter/net_http.rb +0 -130
  88. data/lib/faraday/adapter/net_http_persistent.rb +0 -48
  89. data/lib/faraday/adapter/patron.rb +0 -72
  90. data/lib/faraday/adapter/rack.rb +0 -58
  91. data/lib/faraday/adapter/typhoeus.rb +0 -123
  92. data/lib/faraday/autoload.rb +0 -84
  93. data/lib/faraday/request/basic_authentication.rb +0 -13
  94. data/lib/faraday/request/multipart.rb +0 -63
  95. data/lib/faraday/request/retry.rb +0 -148
  96. data/lib/faraday/request/token_authentication.rb +0 -15
  97. data/lib/faraday/upload_io.rb +0 -67
  98. data/script/cached-bundle +0 -46
  99. data/script/console +0 -7
  100. data/script/generate_certs +0 -42
  101. data/script/package +0 -7
  102. data/script/proxy-server +0 -42
  103. data/script/release +0 -17
  104. data/script/s3-put +0 -71
  105. data/script/server +0 -36
  106. data/script/test +0 -172
  107. data/test/adapters/default_test.rb +0 -14
  108. data/test/adapters/em_http_test.rb +0 -20
  109. data/test/adapters/em_synchrony_test.rb +0 -20
  110. data/test/adapters/excon_test.rb +0 -20
  111. data/test/adapters/httpclient_test.rb +0 -21
  112. data/test/adapters/integration.rb +0 -254
  113. data/test/adapters/logger_test.rb +0 -82
  114. data/test/adapters/net_http_persistent_test.rb +0 -20
  115. data/test/adapters/net_http_test.rb +0 -14
  116. data/test/adapters/patron_test.rb +0 -20
  117. data/test/adapters/rack_test.rb +0 -31
  118. data/test/adapters/test_middleware_test.rb +0 -114
  119. data/test/adapters/typhoeus_test.rb +0 -28
  120. data/test/authentication_middleware_test.rb +0 -65
  121. data/test/composite_read_io_test.rb +0 -111
  122. data/test/connection_test.rb +0 -522
  123. data/test/env_test.rb +0 -218
  124. data/test/helper.rb +0 -81
  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 -177
  128. data/test/middleware_stack_test.rb +0 -173
  129. data/test/multibyte.txt +0 -1
  130. data/test/options_test.rb +0 -252
  131. data/test/parameters_test.rb +0 -64
  132. data/test/request_middleware_test.rb +0 -142
  133. data/test/response_middleware_test.rb +0 -72
  134. data/test/strawberry.rb +0 -2
  135. data/test/utils_test.rb +0 -58
@@ -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,183 @@
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
+ return "#{parent}%5B%5D" if value.empty?
66
+
67
+ buffer = +''
68
+ value.each_with_index do |val, index|
69
+ new_parent = if @array_indices
70
+ "#{parent}%5B#{index}%5D"
71
+ else
72
+ "#{parent}%5B%5D"
73
+ end
74
+ buffer << "#{encode_pair(new_parent, val)}&"
75
+ end
76
+ buffer.chop
77
+ end
78
+ end
79
+
80
+ # Sub-module for decoding query-string into parameters.
81
+ module DecodeMethods
82
+ # @param query [nil, String]
83
+ #
84
+ # @return [Array<Array, String>] the decoded params
85
+ #
86
+ # @raise [TypeError] if the nesting is incorrect
87
+ def decode(query)
88
+ return nil if query.nil?
89
+
90
+ params = {}
91
+ query.split('&').each do |pair|
92
+ next if pair.empty?
93
+
94
+ key, value = pair.split('=', 2)
95
+ key = unescape(key)
96
+ value = unescape(value.tr('+', ' ')) if value
97
+ decode_pair(key, value, params)
98
+ end
99
+
100
+ dehash(params, 0)
101
+ end
102
+
103
+ protected
104
+
105
+ SUBKEYS_REGEX = /[^\[\]]+(?:\]?\[\])?/.freeze
106
+
107
+ def decode_pair(key, value, context)
108
+ subkeys = key.scan(SUBKEYS_REGEX)
109
+ subkeys.each_with_index do |subkey, i|
110
+ is_array = subkey =~ /[\[\]]+\Z/
111
+ subkey = Regexp.last_match.pre_match if is_array
112
+ last_subkey = i == subkeys.length - 1
113
+
114
+ context = prepare_context(context, subkey, is_array, last_subkey)
115
+ add_to_context(is_array, context, value, subkey) if last_subkey
116
+ end
117
+ end
118
+
119
+ def prepare_context(context, subkey, is_array, last_subkey)
120
+ if !last_subkey || is_array
121
+ context = new_context(subkey, is_array, context)
122
+ end
123
+ if context.is_a?(Array) && !is_array
124
+ context = match_context(context, subkey)
125
+ end
126
+ context
127
+ end
128
+
129
+ def new_context(subkey, is_array, context)
130
+ value_type = is_array ? Array : Hash
131
+ if context[subkey] && !context[subkey].is_a?(value_type)
132
+ raise TypeError, "expected #{value_type.name} " \
133
+ "(got #{context[subkey].class.name}) for param `#{subkey}'"
134
+ end
135
+
136
+ context[subkey] ||= value_type.new
137
+ end
138
+
139
+ def match_context(context, subkey)
140
+ context << {} if !context.last.is_a?(Hash) || context.last.key?(subkey)
141
+ context.last
142
+ end
143
+
144
+ def add_to_context(is_array, context, value, subkey)
145
+ is_array ? context << value : context[subkey] = value
146
+ end
147
+
148
+ # Internal: convert a nested hash with purely numeric keys into an array.
149
+ # FIXME: this is not compatible with Rack::Utils.parse_nested_query
150
+ # @!visibility private
151
+ def dehash(hash, depth)
152
+ hash.each do |key, value|
153
+ hash[key] = dehash(value, depth + 1) if value.is_a?(Hash)
154
+ end
155
+
156
+ if depth.positive? && !hash.empty? && hash.keys.all? { |k| k =~ /^\d+$/ }
157
+ hash.sort.map(&:last)
158
+ else
159
+ hash
160
+ end
161
+ end
162
+ end
163
+
164
+ # This is the default encoder for Faraday requests.
165
+ # Using this encoder, parameters will be encoded respecting their structure,
166
+ # so you can send objects such as Arrays or Hashes as parameters
167
+ # for your requests.
168
+ module NestedParamsEncoder
169
+ class << self
170
+ attr_accessor :sort_params, :array_indices
171
+
172
+ extend Forwardable
173
+ def_delegators :'Faraday::Utils', :escape, :unescape
174
+ end
175
+
176
+ # Useful default for OAuth and caching.
177
+ @sort_params = true
178
+ @array_indices = false
179
+
180
+ extend EncodeMethods
181
+ extend DecodeMethods
182
+ end
183
+ end
data/lib/faraday/error.rb CHANGED
@@ -1,23 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Faraday namespace.
1
4
  module Faraday
2
- class Error < StandardError; end
3
- class MissingDependency < Error; end
5
+ # Faraday error base class.
6
+ class Error < StandardError
7
+ attr_reader :response, :wrapped_exception
4
8
 
5
- class ClientError < Error
6
- attr_reader :response
7
-
8
- def initialize(ex, response = nil)
9
- @wrapped_exception = nil
10
- @response = response
11
-
12
- if ex.respond_to?(:backtrace)
13
- super(ex.message)
14
- @wrapped_exception = ex
15
- elsif ex.respond_to?(:each_key)
16
- super("the server responded with status #{ex[:status]}")
17
- @response = ex
18
- else
19
- super(ex.to_s)
20
- end
9
+ def initialize(exc = nil, response = nil)
10
+ @wrapped_exception = nil unless defined?(@wrapped_exception)
11
+ @response = nil unless defined?(@response)
12
+ super(exc_msg_and_response!(exc, response))
21
13
  end
22
14
 
23
15
  def backtrace
@@ -29,25 +21,127 @@ module Faraday
29
21
  end
30
22
 
31
23
  def inspect
32
- %(#<#{self.class}>)
24
+ inner = +''
25
+ inner << " wrapped=#{@wrapped_exception.inspect}" if @wrapped_exception
26
+ inner << " response=#{@response.inspect}" if @response
27
+ inner << " #{super}" if inner.empty?
28
+ %(#<#{self.class}#{inner}>)
29
+ end
30
+
31
+ def response_status
32
+ @response[:status] if @response
33
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 - URI object with the url requested.
56
+ # :url_path - String with the url path requested.
57
+ # :params - String key/value hash of query params
58
+ # present in the request.
59
+ # :headers - String key/value hash of HTTP request
60
+ # header values.
61
+ # :body - String HTTP request body.
62
+ #
63
+ # If a subclass has to call this, then it should pass a string message
64
+ # to `super`. See NilStatusError.
65
+ def exc_msg_and_response!(exc, response = nil)
66
+ if @response.nil? && @wrapped_exception.nil?
67
+ @wrapped_exception, msg, @response = exc_msg_and_response(exc, response)
68
+ return msg
69
+ end
70
+
71
+ exc.to_s
72
+ end
73
+
74
+ # Pulls out potential parent exception and response hash.
75
+ def exc_msg_and_response(exc, response = nil)
76
+ return [exc, exc.message, response] if exc.respond_to?(:backtrace)
77
+
78
+ return [nil, "the server responded with status #{exc[:status]}", exc] \
79
+ if exc.respond_to?(:each_key)
80
+
81
+ [nil, exc.to_s, response]
82
+ end
83
+ end
84
+
85
+ # Faraday client error class. Represents 4xx status responses.
86
+ class ClientError < Error
87
+ end
88
+
89
+ # Raised by Faraday::Response::RaiseError in case of a 400 response.
90
+ class BadRequestError < ClientError
34
91
  end
35
92
 
36
- class ConnectionFailed < ClientError; end
37
- class ResourceNotFound < ClientError; end
38
- class ParsingError < ClientError; end
93
+ # Raised by Faraday::Response::RaiseError in case of a 401 response.
94
+ class UnauthorizedError < ClientError
95
+ end
96
+
97
+ # Raised by Faraday::Response::RaiseError in case of a 403 response.
98
+ class ForbiddenError < ClientError
99
+ end
39
100
 
40
- class TimeoutError < ClientError
41
- def initialize(ex = nil)
42
- super(ex || "timeout")
101
+ # Raised by Faraday::Response::RaiseError in case of a 404 response.
102
+ class ResourceNotFound < ClientError
103
+ end
104
+
105
+ # Raised by Faraday::Response::RaiseError in case of a 407 response.
106
+ class ProxyAuthError < ClientError
107
+ end
108
+
109
+ # Raised by Faraday::Response::RaiseError in case of a 409 response.
110
+ class ConflictError < ClientError
111
+ end
112
+
113
+ # Raised by Faraday::Response::RaiseError in case of a 422 response.
114
+ class UnprocessableEntityError < ClientError
115
+ end
116
+
117
+ # Faraday server error class. Represents 5xx status responses.
118
+ class ServerError < Error
119
+ end
120
+
121
+ # A unified client error for timeouts.
122
+ class TimeoutError < ServerError
123
+ def initialize(exc = 'timeout', response = nil)
124
+ super(exc, response)
43
125
  end
44
126
  end
45
127
 
46
- class SSLError < ClientError
128
+ # Raised by Faraday::Response::RaiseError in case of a nil status in response.
129
+ class NilStatusError < ServerError
130
+ def initialize(exc, response = nil)
131
+ exc_msg_and_response!(exc, response)
132
+ super('http status could not be derived from the server response')
133
+ end
134
+ end
135
+
136
+ # A unified error for failed connections.
137
+ class ConnectionFailed < Error
138
+ end
139
+
140
+ # A unified client error for SSL errors.
141
+ class SSLError < Error
47
142
  end
48
143
 
49
- [:MissingDependency, :ClientError, :ConnectionFailed, :ResourceNotFound,
50
- :ParsingError, :TimeoutError, :SSLError].each do |const|
51
- Error.const_set(const, Faraday.const_get(const))
144
+ # Raised by middlewares that parse the response, like the JSON response middleware.
145
+ class ParsingError < Error
52
146
  end
53
147
  end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pp'
4
+
5
+ module Faraday
6
+ module Logging
7
+ # Serves as an integration point to customize logging
8
+ class Formatter
9
+ extend Forwardable
10
+
11
+ DEFAULT_OPTIONS = { headers: true, bodies: false,
12
+ log_level: :info }.freeze
13
+
14
+ def initialize(logger:, options:)
15
+ @logger = logger
16
+ @filter = []
17
+ @options = DEFAULT_OPTIONS.merge(options)
18
+ end
19
+
20
+ def_delegators :@logger, :debug, :info, :warn, :error, :fatal
21
+
22
+ def request(env)
23
+ request_log = proc do
24
+ "#{env.method.upcase} #{apply_filters(env.url.to_s)}"
25
+ end
26
+ public_send(log_level, 'request', &request_log)
27
+
28
+ log_headers('request', env.request_headers) if log_headers?(:request)
29
+ log_body('request', env[:body]) if env[:body] && log_body?(:request)
30
+ end
31
+
32
+ def response(env)
33
+ status = proc { "Status #{env.status}" }
34
+ public_send(log_level, 'response', &status)
35
+
36
+ log_headers('response', env.response_headers) if log_headers?(:response)
37
+ log_body('response', env[:body]) if env[:body] && log_body?(:response)
38
+ end
39
+
40
+ def filter(filter_word, filter_replacement)
41
+ @filter.push([filter_word, filter_replacement])
42
+ end
43
+
44
+ private
45
+
46
+ def dump_headers(headers)
47
+ headers.map { |k, v| "#{k}: #{v.inspect}" }.join("\n")
48
+ end
49
+
50
+ def dump_body(body)
51
+ if body.respond_to?(:to_str)
52
+ body.to_str
53
+ else
54
+ pretty_inspect(body)
55
+ end
56
+ end
57
+
58
+ def pretty_inspect(body)
59
+ body.pretty_inspect
60
+ end
61
+
62
+ def log_headers?(type)
63
+ case @options[:headers]
64
+ when Hash
65
+ @options[:headers][type]
66
+ else
67
+ @options[:headers]
68
+ end
69
+ end
70
+
71
+ def log_body?(type)
72
+ case @options[:bodies]
73
+ when Hash
74
+ @options[:bodies][type]
75
+ else
76
+ @options[:bodies]
77
+ end
78
+ end
79
+
80
+ def apply_filters(output)
81
+ @filter.each do |pattern, replacement|
82
+ output = output.to_s.gsub(pattern, replacement)
83
+ end
84
+ output
85
+ end
86
+
87
+ def log_level
88
+ unless %i[debug info warn error fatal].include?(@options[:log_level])
89
+ return :info
90
+ end
91
+
92
+ @options[:log_level]
93
+ end
94
+
95
+ def log_headers(type, headers)
96
+ headers_log = proc { apply_filters(dump_headers(headers)) }
97
+ public_send(log_level, type, &headers_log)
98
+ end
99
+
100
+ def log_body(type, body)
101
+ body_log = proc { apply_filters(dump_body(body)) }
102
+ public_send(log_level, type, &body_log)
103
+ end
104
+ end
105
+ end
106
+ 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,30 @@
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
4
7
 
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
8
+ attr_reader :app, :options
18
9
 
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?
10
+ def initialize(app = nil, options = {})
11
+ @app = app
12
+ @options = options
26
13
  end
27
14
 
28
- def self.inherited(subclass)
29
- super
30
- subclass.send(:load_error=, self.load_error)
15
+ def call(env)
16
+ on_request(env) if respond_to?(:on_request)
17
+ app.call(env).on_complete do |environment|
18
+ on_complete(environment) if respond_to?(:on_complete)
19
+ end
31
20
  end
32
21
 
33
- def initialize(app = nil)
34
- @app = app
22
+ def close
23
+ if app.respond_to?(:close)
24
+ app.close
25
+ else
26
+ warn "#{app} does not implement \#close!"
27
+ end
35
28
  end
36
29
  end
37
30
  end