nethttputils 0.3.2.11 → 0.4.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/nethttputils.rb +62 -42
- 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: 3a982e237dae69aa1f18645e6e63d231bb22d5e3
|
4
|
+
data.tar.gz: 71f6c6e79050d656e9bb8c290caa11e013acf386
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e14f163d07b052595d502d07a3d104bcee3c6fbefc6169495f778e589dc80562817912f7fec3183741fa56379a7c6d6bd9fbd0ab3b8b05cb1bae9b2b671eacc5
|
7
|
+
data.tar.gz: 6d8df37fb3fedc5ca757fe8345338421a55ff15283ad5f2456a4a1559de9bc6fe98551aabc56549fc27006a014e1d1702295f1bc19f8984d5eed1b7d82324579
|
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: no_redirect,
|
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
|
@@ -371,20 +395,20 @@ if $0 == __FILE__
|
|
371
395
|
server = WEBrick::HTTPServer.new Port: 8000
|
372
396
|
server.mount_proc "/1" do |req, res|
|
373
397
|
next unless "GET" == req.request_method
|
374
|
-
res.cookies.push WEBrick::Cookie.new
|
375
|
-
res.cookies.push WEBrick::Cookie.new
|
376
|
-
res.cookies.push WEBrick::Cookie.new
|
377
|
-
res.cookies.push WEBrick::Cookie.new
|
378
|
-
res.cookies.push WEBrick::Cookie.new
|
379
|
-
res.cookies.push WEBrick::Cookie.new
|
398
|
+
res.cookies.push WEBrick::Cookie.new "1", "2"
|
399
|
+
res.cookies.push WEBrick::Cookie.new "3", "4"
|
400
|
+
res.cookies.push WEBrick::Cookie.new "8", "9"
|
401
|
+
res.cookies.push WEBrick::Cookie.new "a", "b"
|
402
|
+
res.cookies.push WEBrick::Cookie.new "1", "5"
|
403
|
+
res.cookies.push WEBrick::Cookie.new "f", "g h"
|
380
404
|
res.status = 300
|
381
405
|
res["location"] = "/2"
|
382
406
|
end
|
383
407
|
server.mount_proc "/2" do |req, res|
|
384
|
-
res.cookies.push WEBrick::Cookie.new
|
385
|
-
res.cookies.push WEBrick::Cookie.new
|
386
|
-
res.cookies.push WEBrick::Cookie.new
|
387
|
-
res.cookies.push WEBrick::Cookie.new
|
408
|
+
res.cookies.push WEBrick::Cookie.new "3", "6=c"
|
409
|
+
res.cookies.push WEBrick::Cookie.new "a", "d e"
|
410
|
+
res.cookies.push WEBrick::Cookie.new "8", ""
|
411
|
+
res.cookies.push WEBrick::Cookie.new "4", "7"
|
388
412
|
end
|
389
413
|
t = Thread.new{ server.start }
|
390
414
|
fail unless %w{ 3=6=c a=d\ e 8= 4=7 1=5 a=b } == p(NetHTTPUtils.request_data("http://localhost:8000/1").
|
@@ -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
|
@@ -501,10 +525,6 @@ if $0 == __FILE__
|
|
501
525
|
end
|
502
526
|
end
|
503
527
|
|
504
|
-
begin
|
505
|
-
fail NetHTTPUtils.request_data "https://oi64.tinypic.com/29z7oxs.jpg?", timeout: 5, max_start_http_retry_delay: -1
|
506
|
-
rescue Net::OpenTimeout => e
|
507
|
-
end
|
508
528
|
## this stopped failing on High Sierra
|
509
529
|
# begin
|
510
530
|
# # https://www.virtualself.co/?
|
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.2"
|
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.2
|
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"
|