better-faraday 1.1.3 → 2.0.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5df15bce61cd943bd8736051604de939682c563cb2836144049661e80dca4e50
4
- data.tar.gz: 6fd2d60429e1684e85d474abacda0343260ecac1cf2cad5fbc9e964dd4087a20
3
+ metadata.gz: a8c5cfa773e01c53223151db865f52ad18b5ab411ad0df1d67415a5bd4ef1e73
4
+ data.tar.gz: dde3e3df19d758f85d156ae357d96cb017e0a2746d7de2d14533a860d0dacd9c
5
5
  SHA512:
6
- metadata.gz: 2a002c9f4cdf85b2f1cdc91c1899d8b6766b18cacfa7e7946cabcdf945e261148bfeeeb2981022179d22ba85509296c3fda9ae5f15991f2d6b8ece3513a9bf73
7
- data.tar.gz: 444c4694d034eb482b7b161dad15c56467e24a56755715d001cecb68626f32db9c495d6745dc50edf9f54211ad8b27f9cb554b3cb28e7ca6fb1c4a7fb406b669
6
+ metadata.gz: e9affc8fce7fe302214440777db7778ecc429d9ca188385ae42b58297a76d4a9db5c6e051313b5bc2f211af287c729bdcf39226652c132ff40b2570ef2ee2ea3
7
+ data.tar.gz: c0baba390fcef6d87131569c948cf3492233e99cb317900a79b459dddb0fc7653b05811b279bf71bc7339384f7f2b581a34c69004af8e847718bf10fd2918ce6
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.6.1
1
+ 2.7.3
@@ -3,7 +3,7 @@
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "better-faraday"
6
- s.version = "1.1.3"
6
+ s.version = "2.0.0"
7
7
  s.author = "Yaroslav Konoplov"
8
8
  s.email = "eahome00@gmail.com"
9
9
  s.summary = "Extends Faraday with useful features."
@@ -13,6 +13,6 @@ Gem::Specification.new do |s|
13
13
  s.files = `git ls-files -z`.split("\x0")
14
14
  s.test_files = `git ls-files -z -- {test,spec,features}/*`.split("\x0")
15
15
  s.require_paths = ["lib"]
16
- s.add_dependency "faraday", "~> 0.12"
17
- s.add_dependency "activesupport", ">= 4.0", "< 6.0"
16
+ s.add_dependency "faraday", ">= 1.0", "< 3.0"
17
+ s.add_dependency "activesupport", ">= 4.0", "< 7.0"
18
18
  end
@@ -2,6 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "json"
5
+ require "net/http"
5
6
  require "faraday"
6
7
  require "faraday/error"
7
8
  require "faraday/options"
@@ -9,50 +10,83 @@ require "faraday/response"
9
10
  require "active_support/core_ext/object/deep_dup"
10
11
  require "active_support/core_ext/string/filters"
11
12
  require "active_support/core_ext/string/inflections"
13
+ require "active_support/core_ext/object/inclusion"
12
14
 
13
15
  Module.new do
14
- def call(env)
15
- env.instance_variable_set(:@request_sent_at, Time.now.utc)
16
+ def call(environment)
17
+ environment.instance_variable_set(:@bf_request_sent_at, Time.now.utc)
16
18
  super
17
19
  end
18
20
 
19
- def save_response(env, status, body, headers = nil, reason_phrase = nil)
20
- env.instance_variable_set(:@response_received_at, Time.now.utc)
21
- env.instance_variable_set(:@request_body, env.body.respond_to?(:read) ? env.body.read : env.body)
21
+ def save_response(environment, *)
22
+ environment.instance_variable_set \
23
+ :@bf_response_received_at,
24
+ Time.now.utc
25
+
26
+ body = environment.body
27
+ value = body.respond_to?(:read) ? body.read : body
28
+ value = value.to_s unless String === value
29
+
30
+ environment.instance_variable_set \
31
+ :@bf_request_body,
32
+ value
33
+
22
34
  super
23
35
  end
24
- end.tap { |m| Faraday::Adapter.send(:prepend, m) }
36
+ end.tap { |m| Faraday::Adapter.prepend(m) }
25
37
 
26
- module Faraday
27
- class Env
28
- attr_reader :request_body, :request_sent_at, :response_received_at
38
+ Module.new do
39
+ def end_transport(request, response)
40
+ headers = request.to_hash
41
+ headers.keys.each { |k| headers[k] = headers[k].join(", ") }
42
+ response.instance_variable_set :@bf_request_headers, headers
43
+ super
29
44
  end
45
+ end.tap { |m| Net::HTTP.prepend(m) }
30
46
 
31
- class Error
32
- attr_reader :response
33
-
34
- def inspect
35
- super.gsub(/\s*\(\s*\)\s*\z/, "")
47
+ Module.new do
48
+ def perform_request(connection, environment)
49
+ super(connection, environment).tap do |response|
50
+ environment.instance_variable_set \
51
+ :@bf_request_headers,
52
+ response.instance_variable_get(:@bf_request_headers)
36
53
  end
37
54
  end
55
+ end.tap { |m| Faraday::Adapter::NetHttp.prepend(m) }
56
+
57
+ module Faraday
58
+ class Env
59
+ attr_reader :bf_request_headers, :bf_request_body, :bf_request_sent_at, :bf_response_received_at
60
+ end
38
61
 
39
62
  class Response
40
- def assert_2xx!
41
- return self if status_2xx?
63
+ def assert_status!(code_or_range)
64
+ within_range = if Range === code_or_range
65
+ status.in?(code_or_range)
66
+ else
67
+ status == code_or_range
68
+ end
69
+
70
+ return self if within_range
42
71
 
43
72
  klass = if status_4xx?
44
- "Faraday::HTTP#{status}".safe_constantize || Faraday::HTTP4xx
73
+ "BetterFaraday::HTTP#{status}".safe_constantize || BetterFaraday::HTTP4xx
74
+ elsif status_5xx?
75
+ "BetterFaraday::HTTP#{status}".safe_constantize || BetterFaraday::HTTP5xx
45
76
  else
46
- Faraday::Error
77
+ BetterFaraday::HTTPError
47
78
  end
48
79
 
49
- error = klass.new("\n#{describe}")
50
- error.instance_variable_set(:@response, self)
51
- raise error
80
+ raise klass.new(self)
52
81
  end
53
82
 
54
- alias ok! assert_2xx! # Short name.
55
- alias assert_success! assert_2xx! # Compatibility.
83
+ def assert_2xx!
84
+ assert_status!(200..299)
85
+ end
86
+
87
+ def assert_200!
88
+ assert_status! 200
89
+ end
56
90
 
57
91
  def status_2xx?
58
92
  status >= 200 && status <= 299
@@ -70,92 +104,91 @@ module Faraday
70
104
  status >= 500 && status <= 599
71
105
  end
72
106
 
73
- def describe
74
- request_headers = __protect_data(env.request_headers.deep_dup)
75
-
76
- if env.request_headers["Content-Type"].to_s.match?(/\bapplication\/json\b/)
77
- request_json = __protect_data(__parse_json(env.request_body.dup))
78
- end
107
+ def inspect
108
+ @inspection_text ||= begin
109
+ request_headers = bf_protect_data(env.bf_request_headers.dup)
110
+ request_body = env.bf_request_body.yield_self { |body| String === body ? body : body.to_s }
111
+ request_body_bytes_count = env.bf_request_body.bytesize
112
+ response_body = env.body.yield_self { |body| String === body ? body : body.to_s }
113
+ response_body_bytes_count = response_body.bytesize
114
+
115
+ if env.bf_request_headers["content-type"].to_s.match?(/\bapplication\/json\b/i)
116
+ request_json = bf_json_dump(bf_protect_data(bf_json_parse(request_body)))
117
+ end
79
118
 
80
- if env.response_headers
81
- response_headers = __protect_data(env.response_headers.deep_dup)
82
- end
119
+ if env.response_headers
120
+ response_headers = bf_protect_data(env.response_headers.to_hash)
121
+ end
83
122
 
84
- if env.response_headers && env.response_headers["Content-Type"].to_s.match?(/\bapplication\/json\b/)
85
- response_json = __protect_data(__parse_json(env.body.dup))
86
- end
123
+ if env.response_headers && env.response_headers["content-type"].to_s.match?(/\bapplication\/json\b/i)
124
+ response_json = bf_json_dump(bf_protect_data(bf_json_parse(response_body)))
125
+ end
87
126
 
88
- lines = [
89
- "",
90
- "-- #{status} #{reason_phrase} --".upcase,
91
- "",
92
- "-- Request URL --",
93
- env.url.to_s,
94
- "",
95
- "-- Request method --",
96
- env.method.to_s.upcase,
97
- "",
98
- "-- Request headers --",
99
- ::JSON.generate(request_headers).yield_self { |t| t.truncate(2048, omission: "... (truncated, full length: #{t.length})") },
100
- "",
101
-
102
- "-- Request body --",
103
- if request_json
104
- ::JSON.generate(request_json)
105
- else
106
- body = env.request_body.to_s.dup
107
- if body.encoding.name == "ASCII-8BIT"
108
- "Binary (#{body.size} bytes)"
109
- else
110
- body
111
- end
112
- end.yield_self { |t| t.truncate(1024, omission: "... (truncated, full length: #{t.length})") },
113
- "",
114
-
115
- "-- Request sent at --",
116
- env.request_sent_at.strftime("%Y-%m-%d %H:%M:%S.%2N") + " UTC",
117
- "",
118
-
119
- "-- Response headers --",
120
- if response_headers
121
- ::JSON.generate(response_headers)
122
- else
123
- env.response_headers.to_s
124
- end.yield_self { |t| t.truncate(2048, omission: "... (truncated, full length: #{t.length})") },
125
- "",
127
+ lines = [
128
+ "-- #{status} #{reason_phrase} --".upcase,
129
+ "",
130
+ "-- Request URL --",
131
+ env.url.to_s,
132
+ "",
133
+ "-- Request Method --",
134
+ env.method.to_s.upcase,
135
+ "",
136
+ "-- Request Headers --",
137
+ bf_json_dump(request_headers).truncate(2048, omission: "... (truncated)"),
138
+ "",
126
139
 
127
- "-- Response body --",
128
- if response_json
129
- ::JSON.generate(response_json)
130
- else
131
- body = env.body.to_s.dup
132
- if body.encoding.name == "ASCII-8BIT"
133
- "Binary (#{body.size} bytes)"
140
+ %[-- Request Body (#{request_body_bytes_count} #{"byte".pluralize(request_body_bytes_count)}) --],
141
+ if request_json
142
+ request_json
134
143
  else
135
- body
136
- end
137
- end.yield_self { |t| t.truncate(2048, omission: "... (truncated, full length: #{t.length})") }
138
- ]
144
+ # String#inspect returns \x{XXXX} for the encoding other than Unicode.
145
+ # [1..-2] removed leading and trailing " added by String#inspect.
146
+ # gsub(/\\"/, "\"") unescapes ".
147
+ request_body.inspect.gsub(/\\"/, "\"")[1..-2]
148
+ end.truncate(2048, omission: "... (truncated)"),
149
+ "",
139
150
 
140
- if env.response_received_at
141
- lines.concat [
151
+ "-- Request Sent At --",
152
+ env.bf_request_sent_at.strftime("%Y-%m-%d %H:%M:%S.%3N") + " UTC",
142
153
  "",
143
- "-- Response received at --",
144
- env.response_received_at.strftime("%Y-%m-%d %H:%M:%S.%2N") + " UTC",
154
+
155
+ "-- Response Headers --",
156
+ if response_headers
157
+ bf_json_dump(response_headers)
158
+ else
159
+ env.response_headers.to_s.inspect.gsub(/\\"/, "\"")[1..-2]
160
+ end.truncate(2048, omission: "... (truncated)"),
145
161
  "",
146
- "-- Response received in --",
147
- "#{((env.response_received_at.to_f - env.request_sent_at.to_f) * 1000.0).round(2)}ms"
162
+
163
+ %[-- Response Body (#{response_body_bytes_count} #{"byte".pluralize(response_body_bytes_count)}) --],
164
+ if response_json
165
+ response_json
166
+ else
167
+ response_body.inspect.gsub(/\\"/, "\"")[1..-2]
168
+ end.truncate(2048, omission: "... (truncated)"),
169
+ ""
148
170
  ]
171
+
172
+ if env.bf_response_received_at
173
+ lines.concat [
174
+ "-- Response Received At --",
175
+ env.bf_response_received_at.strftime("%Y-%m-%d %H:%M:%S.%3N") + " UTC",
176
+ "",
177
+ "-- Response Received In --",
178
+ "#{((env.bf_response_received_at.to_f - env.bf_request_sent_at.to_f) * 1000.0).ceil(3)}ms",
179
+ ""
180
+ ]
181
+ end
182
+
183
+ lines.join("\n").freeze
149
184
  end
150
185
 
151
- lines.join("\n") + "\n"
186
+ @inspection_text.dup
152
187
  end
153
188
 
154
- alias inspect describe
155
-
156
189
  private
157
190
 
158
- def __parse_json(json)
191
+ def bf_json_parse(json)
159
192
  return nil unless ::String === json
160
193
  data = ::JSON.parse(json)
161
194
  data if ::Hash === data || ::Array === data
@@ -163,30 +196,58 @@ module Faraday
163
196
  nil
164
197
  end
165
198
 
166
- def __protect_data(data)
167
- return data.map(&method(:__protect_data)) if ::Array === data
199
+ def bf_json_dump(data)
200
+ ::JSON.generate(data, space: " ", object_nl: " ", array_nl: " ")
201
+ end
202
+
203
+ def bf_protect_data(data)
204
+ return data.map(&method(:bf_protect_data)) if ::Array === data
168
205
  return data unless ::Hash === data
206
+
207
+ signs = BetterFaraday.sensitive_data_signs
208
+
169
209
  data.each_with_object({}) do |(key, value), memo|
170
- memo[key] = if key.to_s.underscore.tr("_", " ").yield_self { |k| Faraday.secrets.any? { |s| k.match?(s) } }
210
+ memo[key] = if key.to_s.underscore.tr("_", " ").yield_self { |k| signs.any? { |r| k.match?(r) } }
171
211
  "SECRET"
172
212
  else
173
- __protect_data(value)
213
+ bf_protect_data(value)
174
214
  end
175
215
  end
176
216
  end
177
217
  end
218
+ end
219
+
220
+ module BetterFaraday
221
+ class HTTPError < Faraday::Error
222
+ def initialize(response)
223
+ super(response.inspect, response)
224
+ end
225
+
226
+ def inspect
227
+ %[#{self.class}\n\n#{response.inspect}]
228
+ end
229
+ end
178
230
 
179
- class HTTP4xx < Error; end
231
+ class HTTP4xx < HTTPError; end
180
232
  class HTTP400 < HTTP4xx; end
181
233
  class HTTP401 < HTTP4xx; end
182
234
  class HTTP403 < HTTP4xx; end
183
235
  class HTTP404 < HTTP4xx; end
184
236
  class HTTP422 < HTTP4xx; end
185
237
  class HTTP429 < HTTP4xx; end
238
+ class HTTP5xx < HTTPError; end
239
+ class HTTP500 < HTTP5xx; end
240
+ class HTTP502 < HTTP5xx; end
241
+ class HTTP503 < HTTP5xx; end
186
242
 
187
243
  class << self
188
- attr_accessor :secrets
244
+ attr_accessor :sensitive_data_signs
189
245
  end
190
246
 
191
- self.secrets = [/\bpass(?:word|phrase)\b/i, /\bauthorization\b/i, /\bsecret\b/i, /\b(:?access)?token\b/i]
247
+ self.sensitive_data_signs = [
248
+ /\bpass(?:word|phrase)\b/i,
249
+ /\bauthorization\b/i,
250
+ /\bsecret\b/i,
251
+ /\b(:?access)?token\b/i
252
+ ]
192
253
  end
metadata CHANGED
@@ -1,29 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: better-faraday
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yaroslav Konoplov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-17 00:00:00.000000000 Z
11
+ date: 2022-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ - - "<"
18
21
  - !ruby/object:Gem::Version
19
- version: '0.12'
22
+ version: '3.0'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '1.0'
30
+ - - "<"
25
31
  - !ruby/object:Gem::Version
26
- version: '0.12'
32
+ version: '3.0'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: activesupport
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -33,7 +39,7 @@ dependencies:
33
39
  version: '4.0'
34
40
  - - "<"
35
41
  - !ruby/object:Gem::Version
36
- version: '6.0'
42
+ version: '7.0'
37
43
  type: :runtime
38
44
  prerelease: false
39
45
  version_requirements: !ruby/object:Gem::Requirement
@@ -43,7 +49,7 @@ dependencies:
43
49
  version: '4.0'
44
50
  - - "<"
45
51
  - !ruby/object:Gem::Version
46
- version: '6.0'
52
+ version: '7.0'
47
53
  description: A gem extending Faraday (popular Ruby HTTP client) with useful features
48
54
  without breaking anything.
49
55
  email: eahome00@gmail.com
@@ -76,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
76
82
  - !ruby/object:Gem::Version
77
83
  version: '0'
78
84
  requirements: []
79
- rubygems_version: 3.0.3
85
+ rubygems_version: 3.1.6
80
86
  signing_key:
81
87
  specification_version: 4
82
88
  summary: Extends Faraday with useful features.