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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4bc1f0212b03ef427e313966fff8e8431f35b0fd
4
- data.tar.gz: 1751888f47d8d2252a52549ec96126c768ebcbba
3
+ metadata.gz: 3a982e237dae69aa1f18645e6e63d231bb22d5e3
4
+ data.tar.gz: 71f6c6e79050d656e9bb8c290caa11e013acf386
5
5
  SHA512:
6
- metadata.gz: a047da71bab1fdfa59c4dc1281654ca95914327ebf248080e884d414fdbce39ab0820c84199a359152c29c7f8a749993e9ddcad68238c44bea8a186b29ebf945
7
- data.tar.gz: 12a74c116dd99b6d0e9c98f5cc4a2cb6f7c33b31cb939478b1e7c4763e8bf52108405d94200da74bdff672bc94870da1bba6d8d81186220e2b9e673a19ecbdec
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 = 30
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 > 500
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: 30, max_read_retry_delay: 3600, patch_request: nil, &block
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 ; request.body = JSON.dump form
130
- request.content_type = "application/json"
131
- when :form ; if form.any?{ |k, v| v.respond_to? :to_path }
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 ; raise "unknown content-type '#{type}'"
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..-1] = "..." if body.size > 500 }}"
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
- Time.now.to_i,
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
- new_uri = URI.join request.uri, URI.escape(response["location"])
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, timeout: 30,
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
- http = start_http http, max_start_http_retry_delay, timeout unless http.is_a? Net::HTTP
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, timeout: timeout,
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("1", "2")
375
- res.cookies.push WEBrick::Cookie.new("3", "4")
376
- res.cookies.push WEBrick::Cookie.new("8", "9")
377
- res.cookies.push WEBrick::Cookie.new("a", "b")
378
- res.cookies.push WEBrick::Cookie.new("1", "5")
379
- res.cookies.push WEBrick::Cookie.new("f", "g h")
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("3", "6=c")
385
- res.cookies.push WEBrick::Cookie.new("a", "d e")
386
- res.cookies.push WEBrick::Cookie.new("8", "")
387
- res.cookies.push WEBrick::Cookie.new("4", "7")
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")) == "502 Bad Gateway"
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/cccccc"],
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.2.11"
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 = `git ls-files -z`.split(?\0) - spec.test_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.3.2.11
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: 2019-06-08 00:00:00.000000000 Z
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"