nethttputils 0.3.3.0 → 0.4.1.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.
- checksums.yaml +4 -4
- data/lib/nethttputils.rb +52 -28
- data/nethttputils.gemspec +4 -2
- metadata +17 -5
- data/.travis.yml +0 -21
- data/Rakefile +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aa8c5d5ae78a7dbad64fe4d0e624666cfcbe1642
|
4
|
+
data.tar.gz: 8d09dcf215b50515dc6033f5ef6b6760f14c844c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c315180c06335286428ffb1aff4c41ba6b1648644dc2c41b3f199c8fe2102238e0323359590bb74db31b487e4499b27c5d9823c0a300bae1eafe9f114a62cc59
|
7
|
+
data.tar.gz: 07b47969d1d87ffd4bdd409b038aef316b770f5d3b4d00d7ad0faa419ac559dfa362548c5f942df3300629a6ba9f5ef630370412e73a80afaef785dfde938bb3
|
data/lib/nethttputils.rb
CHANGED
@@ -18,19 +18,23 @@ module NetHTTPUtils
|
|
18
18
|
attr_reader :code
|
19
19
|
def initialize body, code = nil
|
20
20
|
@code = code
|
21
|
+
body = body[0...997] + "..." if body.size > 1000
|
21
22
|
super "HTTP error ##{code.inspect} #{body}"
|
22
23
|
end
|
23
24
|
end
|
25
|
+
class EOFError_from_rbuf_fill < StandardError
|
26
|
+
end
|
24
27
|
|
25
28
|
class << self
|
26
29
|
|
27
30
|
def remove_tags str
|
28
|
-
str.gsub(/<script( [a-z]+="[^"]*")*>.*?<\/script>/m, "").
|
29
|
-
gsub(/<style( [a-z]+="[^"]*")*>.*?<\/style>/m, "").
|
31
|
+
str.gsub(/<script( [a-z-]+="[^"]*")*>.*?<\/script>/m, "").
|
32
|
+
gsub(/<style( [a-z-]+="[^"]*")*>.*?<\/style>/m, "").
|
30
33
|
gsub(/<[^>]*>/, "").split(?\n).map(&:strip).reject(&:empty?).join(?\n)
|
31
34
|
end
|
32
35
|
|
33
|
-
def start_http url, max_start_http_retry_delay = 3600, timeout =
|
36
|
+
def start_http url, max_start_http_retry_delay = 3600, timeout = nil, no_redirect = false, proxy = nil
|
37
|
+
timeout ||= 30
|
34
38
|
uri = url
|
35
39
|
uri = URI.parse begin
|
36
40
|
URI url
|
@@ -42,6 +46,7 @@ module NetHTTPUtils
|
|
42
46
|
begin
|
43
47
|
Net::HTTP.start(
|
44
48
|
uri.host, uri.port,
|
49
|
+
*(proxy.split ?: if proxy),
|
45
50
|
use_ssl: uri.scheme == "https",
|
46
51
|
verify_mode: OpenSSL::SSL::VERIFY_NONE,
|
47
52
|
**({open_timeout: timeout}), # if timeout
|
@@ -54,7 +59,7 @@ module NetHTTPUtils
|
|
54
59
|
def << msg
|
55
60
|
@@buffer ||= "[Net::HTTP debug] "
|
56
61
|
@@buffer.concat msg
|
57
|
-
@@buffer = @@buffer[0...997] + "..." if @@buffer.size >
|
62
|
+
@@buffer = @@buffer[0...997] + "..." if @@buffer.size > 1000
|
58
63
|
return unless @@buffer.end_with? ?\n
|
59
64
|
NetHTTPUtils.logger.debug @@buffer.sub ?\n, " "
|
60
65
|
@@buffer = nil
|
@@ -63,7 +68,7 @@ module NetHTTPUtils
|
|
63
68
|
end ) if logger.level == Logger::DEBUG # use `logger.debug?`?
|
64
69
|
http
|
65
70
|
end
|
66
|
-
rescue Errno::ECONNREFUSED => e
|
71
|
+
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ECONNRESET => e
|
67
72
|
if max_start_http_retry_delay < delay *= 2
|
68
73
|
e.message.concat " to #{uri}"
|
69
74
|
raise
|
@@ -71,10 +76,6 @@ module NetHTTPUtils
|
|
71
76
|
logger.warn "retrying in #{delay} seconds because of #{e.class} '#{e.message}'"
|
72
77
|
sleep delay
|
73
78
|
retry
|
74
|
-
rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ECONNRESET => e
|
75
|
-
logger.warn "retrying in 5 seconds because of #{e.class} '#{e.message}'"
|
76
|
-
sleep 5
|
77
|
-
retry
|
78
79
|
rescue SocketError => e
|
79
80
|
if max_start_http_retry_delay < delay *= 2
|
80
81
|
e.message.concat " to #{uri}"
|
@@ -100,7 +101,8 @@ module NetHTTPUtils
|
|
100
101
|
end
|
101
102
|
|
102
103
|
private
|
103
|
-
def read http, mtd = :GET, type = :form, form: {}, header: {}, auth: nil, timeout:
|
104
|
+
def read http, mtd = :GET, type = :form, form: {}, header: {}, auth: nil, timeout: nil, no_redirect: false, max_read_retry_delay: 3600, patch_request: nil, &block
|
105
|
+
timeout ||= 30
|
104
106
|
logger = NetHTTPUtils.logger
|
105
107
|
|
106
108
|
uri = http.instance_variable_get :@uri
|
@@ -126,15 +128,20 @@ module NetHTTPUtils
|
|
126
128
|
request.basic_auth *auth if auth
|
127
129
|
if (mtd == :POST || mtd == :PATCH) && !form.empty?
|
128
130
|
case type
|
129
|
-
when :json
|
130
|
-
|
131
|
-
|
131
|
+
when :json
|
132
|
+
request.body = JSON.dump form
|
133
|
+
request.content_type = "application/json"
|
134
|
+
when :multipart
|
135
|
+
request.set_form form, "multipart/form-data"
|
136
|
+
when :form
|
137
|
+
if form.any?{ |k, v| v.respond_to? :to_path }
|
132
138
|
request.set_form form, "multipart/form-data"
|
133
139
|
else
|
134
140
|
request.set_form_data form
|
135
141
|
request.content_type = "application/x-www-form-urlencoded;charset=UTF-8"
|
136
142
|
end
|
137
|
-
else
|
143
|
+
else
|
144
|
+
raise "unknown content-type '#{type}'"
|
138
145
|
end
|
139
146
|
end
|
140
147
|
header.each{ |k, v| request[k.to_s] = v.is_a?(Array) ? v.first : v }
|
@@ -155,7 +162,7 @@ module NetHTTPUtils
|
|
155
162
|
request.each_header.map{ |k, v| "-H \"#{k}: #{v}\" " unless k == "host" }.join
|
156
163
|
}#{curl_form}'#{uri.scheme}://#{uri.host}#{uri.path}#{"?#{uri.query}" if uri.query && !uri.query.empty?}'"
|
157
164
|
logger.debug "> header: #{request.each_header.to_a}"
|
158
|
-
logger.debug "> body: #{request.body.inspect.tap{ |body| body[997
|
165
|
+
logger.debug "> body: #{request.body.inspect.tap{ |body| body.replace body[0...997] + "..." if body.size > 1000 }}"
|
159
166
|
# TODO this is buggy -- mixes lines from different files into one line
|
160
167
|
stack = caller.reverse.map do |level|
|
161
168
|
/((?:[^\/:]+\/)?[^\/:]+):([^:]+)/.match(level).captures
|
@@ -169,15 +176,21 @@ module NetHTTPUtils
|
|
169
176
|
delay = 5
|
170
177
|
response = begin
|
171
178
|
http.request request, &block
|
172
|
-
rescue Errno::ECONNREFUSED, Net::ReadTimeout, Net::OpenTimeout, Zlib::BufError, Errno::ECONNRESET, OpenSSL::SSL::SSLError => e
|
179
|
+
rescue Errno::ECONNREFUSED, Net::ReadTimeout, Net::OpenTimeout, Zlib::BufError, Errno::ECONNRESET, OpenSSL::SSL::SSLError, Errno::ETIMEDOUT, Errno::ENETUNREACH => e
|
173
180
|
raise if max_read_retry_delay < delay *= 2
|
174
181
|
logger.error "retrying in #{delay} seconds because of #{e.class} '#{e.message}' at: #{request.uri}"
|
175
182
|
sleep delay
|
176
183
|
retry
|
184
|
+
rescue EOFError => e
|
185
|
+
raise unless e.backtrace.empty?
|
186
|
+
# https://bugs.ruby-lang.org/issues/13018
|
187
|
+
# https://blog.kalina.tech/2019/04/exception-without-backtrace-in-ruby.html
|
188
|
+
raise EOFError_from_rbuf_fill.new "probably the old Ruby empty backtrace EOFError exception from net/protocol.rb"
|
177
189
|
end
|
178
190
|
# response.instance_variable_set "@nethttputils_close", http.method(:finish)
|
179
191
|
# response.singleton_class.instance_eval{ attr_accessor :nethttputils_socket_to_close }
|
180
192
|
|
193
|
+
now = Time.now
|
181
194
|
remaining, reset_time, current_timestamp = if response.key? "x-ratelimit-userremaining"
|
182
195
|
logger.debug "x-ratelimit-clientremaining: #{response.fetch("x-ratelimit-clientremaining").to_i}"
|
183
196
|
[
|
@@ -189,7 +202,13 @@ module NetHTTPUtils
|
|
189
202
|
[
|
190
203
|
response.fetch("x-rate-limit-remaining").to_i,
|
191
204
|
response.fetch("x-rate-limit-reset").to_i,
|
192
|
-
|
205
|
+
now.to_i,
|
206
|
+
]
|
207
|
+
elsif response.key? "x-ratelimit-remaining"
|
208
|
+
[
|
209
|
+
response.fetch("x-ratelimit-remaining").to_i,
|
210
|
+
now + response.fetch("x-ratelimit-reset").to_i,
|
211
|
+
now.to_i,
|
193
212
|
]
|
194
213
|
end
|
195
214
|
if remaining
|
@@ -215,9 +234,13 @@ module NetHTTPUtils
|
|
215
234
|
end
|
216
235
|
|
217
236
|
case response.code
|
237
|
+
when /\A20/
|
238
|
+
response
|
218
239
|
when /\A30\d\z/
|
240
|
+
next response if no_redirect
|
219
241
|
logger.info "redirect: #{response["location"]}"
|
220
|
-
|
242
|
+
require "addressable"
|
243
|
+
new_uri = URI.join request.uri.to_s, Addressable::URI.escape(response["location"])
|
221
244
|
new_host = new_uri.host
|
222
245
|
raise Error.new "redirected in place" if new_uri == http.instance_variable_get(:@uri)
|
223
246
|
if http.address != new_host ||
|
@@ -225,7 +248,7 @@ module NetHTTPUtils
|
|
225
248
|
http.use_ssl? != (new_uri.scheme == "https")
|
226
249
|
logger.debug "changing host from '#{http.address}' to '#{new_host}'"
|
227
250
|
# http.finish # why commented out?
|
228
|
-
http = NetHTTPUtils.start_http new_uri, http.instance_variable_get(:@max_start_http_retry_delay), timeout
|
251
|
+
http = NetHTTPUtils.start_http new_uri, http.instance_variable_get(:@max_start_http_retry_delay), timeout, no_redirect
|
229
252
|
end
|
230
253
|
if request.method == "POST"
|
231
254
|
logger.info "POST redirects to GET (RFC)"
|
@@ -261,8 +284,6 @@ module NetHTTPUtils
|
|
261
284
|
end
|
262
285
|
}"
|
263
286
|
response
|
264
|
-
when /\A20/
|
265
|
-
response
|
266
287
|
else
|
267
288
|
logger.warn "code #{response.code} at #{request.method} #{request.uri} from #{
|
268
289
|
[__FILE__, caller.map{ |i| i[/(?<=:)\d+/] }].join ?:
|
@@ -283,11 +304,13 @@ module NetHTTPUtils
|
|
283
304
|
|
284
305
|
require "set"
|
285
306
|
@@_405 ||= Set.new
|
286
|
-
def request_data http, mtd = :GET, type = :form, form: {}, header: {}, auth: nil,
|
307
|
+
def request_data http, mtd = :GET, type = :form, form: {}, header: {}, auth: nil, proxy: nil,
|
308
|
+
timeout: nil, no_redirect: false,
|
287
309
|
max_start_http_retry_delay: 3600,
|
288
310
|
max_read_retry_delay: 3600,
|
289
311
|
patch_request: nil, &block
|
290
|
-
|
312
|
+
timeout ||= 30
|
313
|
+
http = start_http http, max_start_http_retry_delay, timeout, no_redirect, *proxy unless http.is_a? Net::HTTP
|
291
314
|
path = http.instance_variable_get(:@uri).path
|
292
315
|
|
293
316
|
check_code = lambda do |body|
|
@@ -318,7 +341,8 @@ module NetHTTPUtils
|
|
318
341
|
check_code.call body
|
319
342
|
end
|
320
343
|
end
|
321
|
-
body = read http, mtd, type, form: form, header: header, auth: auth,
|
344
|
+
body = read http, mtd, type, form: form, header: header, auth: auth,
|
345
|
+
timeout: timeout, no_redirect: no_redirect,
|
322
346
|
max_read_retry_delay: max_read_retry_delay,
|
323
347
|
patch_request: patch_request, &block
|
324
348
|
check_code.call body
|
@@ -467,16 +491,16 @@ if $0 == __FILE__
|
|
467
491
|
fail unless NetHTTPUtils.method(:read).call(NetHTTPUtils.start_http("http://httpstat.us/400")) == "400 Bad Request"
|
468
492
|
fail unless NetHTTPUtils.method(:read).call(NetHTTPUtils.start_http("http://httpstat.us/404")) == "404 Not Found"
|
469
493
|
fail unless NetHTTPUtils.method(:read).call(NetHTTPUtils.start_http("http://httpstat.us/500")) == "500 Internal Server Error"
|
470
|
-
fail unless NetHTTPUtils.method(:read).call(NetHTTPUtils.start_http("http://httpstat.us/502"))
|
494
|
+
fail unless NetHTTPUtils.method(:read).call(NetHTTPUtils.start_http("http://httpstat.us/502")).start_with? "httpstat.us | 502: Bad gateway\nError\n502\n"
|
471
495
|
fail unless NetHTTPUtils.method(:read).call(NetHTTPUtils.start_http("http://httpstat.us/503")) == "503 Service Unavailable"
|
472
496
|
[
|
473
|
-
["https://imgur.com/a/
|
474
|
-
["https://imgur.com/mM4Dh7Z"],
|
497
|
+
# ["https://imgur.com/a/oacI3gl"], # TODO: Imgur now hangs on these pages, I guess they had to be some 404 error page
|
498
|
+
# ["https://imgur.com/mM4Dh7Z"], # TODO: Imgur now hangs on these pages, I guess they had to be some 404 error page
|
475
499
|
["https://i.redd.it/si758zk7r5xz.jpg", "HTTP error #404 <image/png>"],
|
476
500
|
].each do |url, expectation|
|
477
501
|
begin
|
478
502
|
puts NetHTTPUtils.remove_tags NetHTTPUtils.request_data url
|
479
|
-
fail
|
503
|
+
fail url
|
480
504
|
rescue NetHTTPUtils::Error => e
|
481
505
|
raise e.code.inspect unless e.code == 404
|
482
506
|
raise e.to_s if e.to_s != expectation if expectation
|
data/nethttputils.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |spec|
|
2
2
|
spec.name = "nethttputils"
|
3
|
-
spec.version = "0.
|
3
|
+
spec.version = "0.4.1.3"
|
4
4
|
spec.summary = "this tool is like a pet that I adopted young and now I depend on, sorry"
|
5
5
|
spec.description = <<-EOF
|
6
6
|
Back in 2015 I was a guy automating things at my job and two scripts had a common need --
|
@@ -21,5 +21,7 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.license = "MIT"
|
22
22
|
|
23
23
|
spec.require_path = "lib"
|
24
|
-
spec.files =
|
24
|
+
spec.files = %w{ LICENSE nethttputils.gemspec lib/nethttputils.rb }
|
25
|
+
|
26
|
+
spec.add_dependency "addressable"
|
25
27
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nethttputils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Victor Maslov aka Nakilon
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
11
|
+
date: 2021-06-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: addressable
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
description: |2
|
14
28
|
Back in 2015 I was a guy automating things at my job and two scripts had a common need --
|
15
29
|
they both had to pass the same credentials to Jenkins (via query params, I guess).
|
@@ -26,9 +40,7 @@ executables: []
|
|
26
40
|
extensions: []
|
27
41
|
extra_rdoc_files: []
|
28
42
|
files:
|
29
|
-
- ".travis.yml"
|
30
43
|
- LICENSE
|
31
|
-
- Rakefile
|
32
44
|
- lib/nethttputils.rb
|
33
45
|
- nethttputils.gemspec
|
34
46
|
homepage: https://github.com/nakilon/nethttputils
|
data/.travis.yml
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
---
|
2
|
-
language: ruby
|
3
|
-
|
4
|
-
script: "ruby lib/nethttputils.rb"
|
5
|
-
|
6
|
-
os:
|
7
|
-
- linux
|
8
|
-
- osx
|
9
|
-
rvm:
|
10
|
-
- ruby-head
|
11
|
-
- 2.5
|
12
|
-
- 2.4
|
13
|
-
- 2.3
|
14
|
-
- 2.2
|
15
|
-
- 2.1
|
16
|
-
- 2.0
|
17
|
-
- jruby-head
|
18
|
-
matrix:
|
19
|
-
allow_failures:
|
20
|
-
# something with `NetHTTPUtils.request_data("http://localhost:8000/?1=2&3=4", form: {1=>3})` test
|
21
|
-
- rvm: jruby-head
|
data/Rakefile
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require "bundler/gem_tasks"
|