better-faraday 1.1.4 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 30c3a63862a5faff00055d0f7fa905b8a67bcb85b3197929a0dcc1b7cce84d5c
4
- data.tar.gz: 1d21b6f8fc0ce3efa6dcfec7fcec79e490a27a7c8b48b8a5d97e6d27d196ef26
3
+ metadata.gz: c8f236710b44dc72e1efa535f4750f9cc782bce797be1d771da23d7f2ff3ded1
4
+ data.tar.gz: 4f9c6d1453f308abb928b234429f68c26345056c6b1ff8df2efc17dafce73bcf
5
5
  SHA512:
6
- metadata.gz: 181d98b5697219d6bc095d275c0335438b148dd0ddf3e0d08d97855c5f4457731d541d83e19d3c8b3b187023171621baffe13d03417a00d4be50a414809a3d0e
7
- data.tar.gz: fcaa327eb416c1ec95e8df522e580a92809ff927f043402f9c998a2797e19eda91b666261280edf89ccf08bfb8c58822399211ba6b8d899d9647b8cf28273001
6
+ metadata.gz: a3a4bb57f6938d021ebf37e9f854e06b55e4022f2ea983a62de1264085c64807a30d8eeeec72c8913b3dd6229c8777293ab2577b4aabd5cc41dd9e1c0b6d3db4
7
+ data.tar.gz: c0f632bb82dd8eeb84a071d12b1f957a9542494278eaa297e774ca71ef2c1a8a52bad868bec86410b74e9d9beafcb0f823b9eb64b8d4cefc8da840f47befc07f
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.4"
6
+ s.version = "2.0.1"
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.17", "< 2.0"
16
+ s.add_dependency "faraday", ">= 1.0", "< 3.0"
17
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)
81
+ end
82
+
83
+ def assert_2xx!
84
+ assert_status!(200..299)
52
85
  end
53
86
 
54
- alias ok! assert_2xx! # Short name.
55
- alias assert_success! assert_2xx! # Compatibility.
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,95 @@ 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
79
-
80
- if env.response_headers
81
- response_headers = __protect_data(env.response_headers.deep_dup)
82
- 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_parse(request_body).yield_self do |data|
117
+ bf_json_dump(bf_protect_data(data)) if data
118
+ end
119
+ end
83
120
 
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
121
+ if env.response_headers
122
+ response_headers = bf_protect_data(env.response_headers.to_hash)
123
+ end
87
124
 
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
125
+ if env.response_headers && env.response_headers["content-type"].to_s.match?(/\bapplication\/json\b/i)
126
+ response_json = bf_json_parse(response_body).yield_self do |data|
127
+ bf_json_dump(bf_protect_data(data)) if data
111
128
  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
- "",
129
+ end
118
130
 
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
- "",
131
+ lines = [
132
+ "-- #{status} #{reason_phrase} --".upcase,
133
+ "",
134
+ "-- Request URL --",
135
+ env.url.to_s,
136
+ "",
137
+ "-- Request Method --",
138
+ env.method.to_s.upcase,
139
+ "",
140
+ "-- Request Headers --",
141
+ bf_json_dump(request_headers).truncate(2048, omission: "... (truncated)"),
142
+ "",
126
143
 
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)"
144
+ %[-- Request Body (#{request_body_bytes_count} #{"byte".pluralize(request_body_bytes_count)}) --],
145
+ if request_json
146
+ request_json
134
147
  else
135
- body
136
- end
137
- end.yield_self { |t| t.truncate(2048, omission: "... (truncated, full length: #{t.length})") }
138
- ]
148
+ # String#inspect returns \x{XXXX} for the encoding other than Unicode.
149
+ # [1..-2] removed leading and trailing " added by String#inspect.
150
+ # gsub(/\\"/, "\"") unescapes ".
151
+ request_body.inspect.gsub(/\\"/, "\"")[1..-2]
152
+ end.truncate(2048, omission: "... (truncated)"),
153
+ "",
139
154
 
140
- if env.response_received_at
141
- lines.concat [
155
+ "-- Request Sent At --",
156
+ env.bf_request_sent_at.strftime("%Y-%m-%d %H:%M:%S.%3N") + " UTC",
142
157
  "",
143
- "-- Response received at --",
144
- env.response_received_at.strftime("%Y-%m-%d %H:%M:%S.%2N") + " UTC",
158
+
159
+ "-- Response Headers --",
160
+ if response_headers
161
+ bf_json_dump(response_headers)
162
+ else
163
+ env.response_headers.to_s.inspect.gsub(/\\"/, "\"")[1..-2]
164
+ end.truncate(2048, omission: "... (truncated)"),
145
165
  "",
146
- "-- Response received in --",
147
- "#{((env.response_received_at.to_f - env.request_sent_at.to_f) * 1000.0).round(2)}ms"
166
+
167
+ %[-- Response Body (#{response_body_bytes_count} #{"byte".pluralize(response_body_bytes_count)}) --],
168
+ if response_json
169
+ response_json
170
+ else
171
+ response_body.inspect.gsub(/\\"/, "\"")[1..-2]
172
+ end.truncate(2048, omission: "... (truncated)"),
173
+ ""
148
174
  ]
175
+
176
+ if env.bf_response_received_at
177
+ lines.concat [
178
+ "-- Response Received At --",
179
+ env.bf_response_received_at.strftime("%Y-%m-%d %H:%M:%S.%3N") + " UTC",
180
+ "",
181
+ "-- Response Received In --",
182
+ "#{((env.bf_response_received_at.to_f - env.bf_request_sent_at.to_f) * 1000.0).ceil(3)}ms",
183
+ ""
184
+ ]
185
+ end
186
+
187
+ lines.join("\n").freeze
149
188
  end
150
189
 
151
- lines.join("\n") + "\n"
190
+ @inspection_text.dup
152
191
  end
153
192
 
154
- alias inspect describe
155
-
156
193
  private
157
194
 
158
- def __parse_json(json)
195
+ def bf_json_parse(json)
159
196
  return nil unless ::String === json
160
197
  data = ::JSON.parse(json)
161
198
  data if ::Hash === data || ::Array === data
@@ -163,30 +200,58 @@ module Faraday
163
200
  nil
164
201
  end
165
202
 
166
- def __protect_data(data)
167
- return data.map(&method(:__protect_data)) if ::Array === data
203
+ def bf_json_dump(data)
204
+ ::JSON.generate(data, space: " ", object_nl: " ", array_nl: " ")
205
+ end
206
+
207
+ def bf_protect_data(data)
208
+ return data.map(&method(:bf_protect_data)) if ::Array === data
168
209
  return data unless ::Hash === data
210
+
211
+ signs = BetterFaraday.sensitive_data_signs
212
+
169
213
  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) } }
214
+ memo[key] = if key.to_s.underscore.tr("_", " ").yield_self { |k| signs.any? { |r| k.match?(r) } }
171
215
  "SECRET"
172
216
  else
173
- __protect_data(value)
217
+ bf_protect_data(value)
174
218
  end
175
219
  end
176
220
  end
177
221
  end
222
+ end
223
+
224
+ module BetterFaraday
225
+ class HTTPError < Faraday::Error
226
+ def initialize(response)
227
+ super(response.inspect, response)
228
+ end
229
+
230
+ def inspect
231
+ %[#{self.class}\n\n#{response.inspect}]
232
+ end
233
+ end
178
234
 
179
- class HTTP4xx < Error; end
235
+ class HTTP4xx < HTTPError; end
180
236
  class HTTP400 < HTTP4xx; end
181
237
  class HTTP401 < HTTP4xx; end
182
238
  class HTTP403 < HTTP4xx; end
183
239
  class HTTP404 < HTTP4xx; end
184
240
  class HTTP422 < HTTP4xx; end
185
241
  class HTTP429 < HTTP4xx; end
242
+ class HTTP5xx < HTTPError; end
243
+ class HTTP500 < HTTP5xx; end
244
+ class HTTP502 < HTTP5xx; end
245
+ class HTTP503 < HTTP5xx; end
186
246
 
187
247
  class << self
188
- attr_accessor :secrets
248
+ attr_accessor :sensitive_data_signs
189
249
  end
190
250
 
191
- self.secrets = [/\bpass(?:word|phrase)\b/i, /\bauthorization\b/i, /\bsecret\b/i, /\b(:?access)?token\b/i]
251
+ self.sensitive_data_signs = [
252
+ /\bpass(?:word|phrase)\b/i,
253
+ /\bauthorization\b/i,
254
+ /\bsecret\b/i,
255
+ /\b(:?access)?token\b/i
256
+ ]
192
257
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: better-faraday
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.4
4
+ version: 2.0.1
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-10-26 00:00:00.000000000 Z
11
+ date: 2022-05-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -16,20 +16,20 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0.17'
19
+ version: '1.0'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '2.0'
22
+ version: '3.0'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: '0.17'
29
+ version: '1.0'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '2.0'
32
+ version: '3.0'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: activesupport
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -82,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
82
82
  - !ruby/object:Gem::Version
83
83
  version: '0'
84
84
  requirements: []
85
- rubygems_version: 3.1.2
85
+ rubygems_version: 3.1.6
86
86
  signing_key:
87
87
  specification_version: 4
88
88
  summary: Extends Faraday with useful features.