better-faraday 1.2.0 → 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 +4 -4
- data/better-faraday.gemspec +2 -2
- data/lib/better-faraday.rb +163 -114
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a8c5cfa773e01c53223151db865f52ad18b5ab411ad0df1d67415a5bd4ef1e73
|
4
|
+
data.tar.gz: dde3e3df19d758f85d156ae357d96cb017e0a2746d7de2d14533a860d0dacd9c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e9affc8fce7fe302214440777db7778ecc429d9ca188385ae42b58297a76d4a9db5c6e051313b5bc2f211af287c729bdcf39226652c132ff40b2570ef2ee2ea3
|
7
|
+
data.tar.gz: c0baba390fcef6d87131569c948cf3492233e99cb317900a79b459dddb0fc7653b05811b279bf71bc7339384f7f2b581a34c69004af8e847718bf10fd2918ce6
|
data/better-faraday.gemspec
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "better-faraday"
|
6
|
-
s.version = "
|
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", ">= 1.0", "<
|
16
|
+
s.add_dependency "faraday", ">= 1.0", "< 3.0"
|
17
17
|
s.add_dependency "activesupport", ">= 4.0", "< 7.0"
|
18
18
|
end
|
data/lib/better-faraday.rb
CHANGED
@@ -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(
|
15
|
-
|
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(
|
20
|
-
|
21
|
-
|
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.
|
36
|
+
end.tap { |m| Faraday::Adapter.prepend(m) }
|
25
37
|
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
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
|
41
|
-
|
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
|
-
"
|
73
|
+
"BetterFaraday::HTTP#{status}".safe_constantize || BetterFaraday::HTTP4xx
|
74
|
+
elsif status_5xx?
|
75
|
+
"BetterFaraday::HTTP#{status}".safe_constantize || BetterFaraday::HTTP5xx
|
45
76
|
else
|
46
|
-
|
77
|
+
BetterFaraday::HTTPError
|
47
78
|
end
|
48
79
|
|
49
|
-
|
50
|
-
|
51
|
-
|
80
|
+
raise klass.new(self)
|
81
|
+
end
|
82
|
+
|
83
|
+
def assert_2xx!
|
84
|
+
assert_status!(200..299)
|
52
85
|
end
|
53
86
|
|
54
|
-
|
55
|
-
|
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
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
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
|
-
|
81
|
-
|
82
|
-
|
119
|
+
if env.response_headers
|
120
|
+
response_headers = bf_protect_data(env.response_headers.to_hash)
|
121
|
+
end
|
83
122
|
|
84
|
-
|
85
|
-
|
86
|
-
|
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
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
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
|
-
|
128
|
-
|
129
|
-
|
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
|
-
|
136
|
-
|
137
|
-
|
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
|
-
|
141
|
-
|
151
|
+
"-- Request Sent At --",
|
152
|
+
env.bf_request_sent_at.strftime("%Y-%m-%d %H:%M:%S.%3N") + " UTC",
|
142
153
|
"",
|
143
|
-
|
144
|
-
|
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
|
-
|
147
|
-
|
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
|
-
|
186
|
+
@inspection_text.dup
|
152
187
|
end
|
153
188
|
|
154
|
-
alias inspect describe
|
155
|
-
|
156
189
|
private
|
157
190
|
|
158
|
-
def
|
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,42 +196,58 @@ module Faraday
|
|
163
196
|
nil
|
164
197
|
end
|
165
198
|
|
166
|
-
def
|
167
|
-
|
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|
|
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
|
-
|
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 <
|
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
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
end
|
191
|
-
|
192
|
-
self.secrets = [/\bpass(?:word|phrase)\b/i, /\bauthorization\b/i, /\bsecret\b/i, /\b(:?access)?token\b/i]
|
193
|
-
end
|
238
|
+
class HTTP5xx < HTTPError; end
|
239
|
+
class HTTP500 < HTTP5xx; end
|
240
|
+
class HTTP502 < HTTP5xx; end
|
241
|
+
class HTTP503 < HTTP5xx; end
|
194
242
|
|
195
243
|
class << self
|
196
|
-
|
197
|
-
Inspection.secrets
|
198
|
-
end
|
199
|
-
|
200
|
-
def secrets=(value)
|
201
|
-
Inspection.secrets = value
|
202
|
-
end
|
244
|
+
attr_accessor :sensitive_data_signs
|
203
245
|
end
|
246
|
+
|
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
|
+
]
|
204
253
|
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:
|
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:
|
11
|
+
date: 2022-03-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -19,7 +19,7 @@ dependencies:
|
|
19
19
|
version: '1.0'
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
22
|
+
version: '3.0'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -29,7 +29,7 @@ dependencies:
|
|
29
29
|
version: '1.0'
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
32
|
+
version: '3.0'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: activesupport
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|