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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9afa291d86c40f37b207744ca23c7e12c330e055
4
- data.tar.gz: 3afb6030d76642efed329bdf322c68dbb3eb2d00
3
+ metadata.gz: aa8c5d5ae78a7dbad64fe4d0e624666cfcbe1642
4
+ data.tar.gz: 8d09dcf215b50515dc6033f5ef6b6760f14c844c
5
5
  SHA512:
6
- metadata.gz: a91b3cf20cbb611ff5e77d8efef83b37c01cabe413431dfb7edf7df9fe4c5eae4d92cf177891b04fd2e4a96b399871fcdc9b9afc2d2dd9926101b2321da5f28c
7
- data.tar.gz: 137f44eee308529b23e5c6d9c592801950ddca31e156a6e0010b0a98f34cd8f758d6810143d34c0994b3ff17e42f1cc8a6d7608cdba9b7638c143781822732fa
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 = 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, 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: false,
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
@@ -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
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.3.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 = `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.3.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: 2019-11-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"