down 5.0.1 → 5.2.2

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
  SHA256:
3
- metadata.gz: 5845204de4f09b03621e6474e9f3032ae9c0ce9823dac21cfc8f435c184c4a30
4
- data.tar.gz: f7f65817661dfc62c4ab74da59ef5f8ad6b90927c50b62da0bf77f833f79c139
3
+ metadata.gz: 5a49023a41da71285f7f87570bc92850fa41291f9efa37a0c34b54ed8d1c1e1a
4
+ data.tar.gz: 87d0aee326bb8752ff853046d3c1bbc32364d8d379ee6fb3bfd55e46fd60532e
5
5
  SHA512:
6
- metadata.gz: 12b2ab829b2912913dc9ba6bfb77dcd8e9a8e909cc58cdc09b25567a936baf361657785a386766a4e6bc01d50c900240af7be694e88d4e68d829dfe0f5b09bef
7
- data.tar.gz: '08ec832345fb6a41ba8888c15f3879a437dce282b809d236b08310dfd2ce9881df18cf663f6a11a69182af47dcc20d3bcf2688f4b32d278cfa5dbe75b9553417'
6
+ metadata.gz: b70f1f09562267bc15ef7ebf54b94e843e440a10dc4aed1c7e39cd55d545895f439f538416cdb9899b74ff803d5e8e749c734050261302848158f99937e7dd81
7
+ data.tar.gz: 9105364a02865aa4c93e5384d6df969277a158a94eb9414b0b6189685a4a5be7bf020ec00437fd2402f92a0aba9f2c3f545b497f71850604bd3af83c79ab6da4
data/CHANGELOG.md CHANGED
@@ -1,3 +1,35 @@
1
+ ## 5.2.2 (2021-05-27)
2
+
3
+ * Add info about received content length in `Down::TooLarge` error (@evheny0)
4
+
5
+ * Relax http.rb constraint to allow versions 5.x (@mgrunberg)
6
+
7
+ ## 5.2.1 (2021-04-26)
8
+
9
+ * Raise `Down::NotModified` on 304 response status in `Down::NetHttp#open` (@ellafeldmann)
10
+
11
+ ## 5.2.0 (2020-09-20)
12
+
13
+ * Add `:uri_normalizer` option to `Down::NetHttp` (@janko)
14
+
15
+ * Add `:http_basic_authentication` option to `Down::NetHttp#open` (@janko)
16
+
17
+ * Fix uninitialized instance variables warnings in `Down::ChunkedIO` (@janko)
18
+
19
+ * Handle unknown HTTP error codes in `Down::NetHttp` (@darndt)
20
+
21
+ ## 5.1.1 (2020-02-04)
22
+
23
+ * Fix keyword arguments warnings on Ruby 2.7 in `Down.download` and `Down.open` (@janko)
24
+
25
+ ## 5.1.0 (2020-01-09)
26
+
27
+ * Fix keyword arguments warnings on Ruby 2.7 (@janko)
28
+
29
+ * Fix `FrozenError` exception in `Down::ChunkedIO#readpartial` (@janko)
30
+
31
+ * Deprecate passing headers as top-level options in `Down::NetHttp` (@janko)
32
+
1
33
  ## 5.0.1 (2019-12-20)
2
34
 
3
35
  * In `Down::NetHttp` only use Addressable normalization if `URI.parse` fails (@coding-chimp)
data/README.md CHANGED
@@ -212,6 +212,7 @@ the `Down::Error` subclasses. This is Down's exception hierarchy:
212
212
  * `Down::TooLarge`
213
213
  * `Down::InvalidUrl`
214
214
  * `Down::TooManyRedirects`
215
+ * `Down::NotModified`
215
216
  * `Down::ResponseError`
216
217
  * `Down::ClientError`
217
218
  * `Down::NotFound`
@@ -333,6 +334,18 @@ Down::NetHttp.open("http://example.com/image.jpg",
333
334
  ssl_verify_mode: OpenSSL::SSL::VERIFY_PEER)
334
335
  ```
335
336
 
337
+ #### URI normalization
338
+
339
+ If the URL isn't parseable by `URI.parse`, `Down::NetHttp` will
340
+ attempt to normalize the URL using [Addressable::URI], URI-escaping
341
+ any potentially unescaped characters. You can change the normalizer
342
+ via the `:uri_normalizer` option:
343
+
344
+ ```rb
345
+ # this skips URL normalization
346
+ Down::NetHttp.download("http://example.com/image.jpg", uri_normalizer: -> (url) { url })
347
+ ```
348
+
336
349
  #### Additional options
337
350
 
338
351
  Any additional options passed to `Down.download` will be forwarded to
@@ -358,8 +371,8 @@ net_http.open("http://example.com/image.jpg")
358
371
  The `Down::Http` backend implements downloads using the [http.rb] gem.
359
372
 
360
373
  ```rb
361
- gem "down", "~> 4.4"
362
- gem "http", "~> 4.0"
374
+ gem "down", "~> 5.0"
375
+ gem "http", "~> 5.0"
363
376
  ```
364
377
  ```rb
365
378
  require "down/http"
@@ -470,12 +483,12 @@ wget.open("http://nature.com/forest.jpg")
470
483
 
471
484
  ## Supported Ruby versions
472
485
 
473
- * MRI 2.2
474
486
  * MRI 2.3
475
487
  * MRI 2.4
476
488
  * MRI 2.5
477
489
  * MRI 2.6
478
- * JRuby
490
+ * MRI 2.7
491
+ * JRuby 9.2
479
492
 
480
493
  ## Development
481
494
 
data/down.gemspec CHANGED
@@ -4,7 +4,7 @@ Gem::Specification.new do |spec|
4
4
  spec.name = "down"
5
5
  spec.version = Down::VERSION
6
6
 
7
- spec.required_ruby_version = ">= 2.1"
7
+ spec.required_ruby_version = ">= 2.3"
8
8
 
9
9
  spec.summary = "Robust streaming downloads using Net::HTTP, HTTP.rb or wget."
10
10
  spec.homepage = "https://github.com/janko/down"
@@ -20,8 +20,14 @@ Gem::Specification.new do |spec|
20
20
  spec.add_development_dependency "minitest", "~> 5.8"
21
21
  spec.add_development_dependency "mocha", "~> 1.5"
22
22
  spec.add_development_dependency "rake"
23
- spec.add_development_dependency "http", "~> 4.0"
23
+ # http 5.0 drop support of ruby 2.3 and 2.4. We still support those versions.
24
+ if RUBY_VERSION >= "2.5"
25
+ spec.add_development_dependency "http", "~> 5.0"
26
+ else
27
+ spec.add_development_dependency "http", "~> 4.3"
28
+ end
24
29
  spec.add_development_dependency "posix-spawn" unless RUBY_ENGINE == "jruby"
25
30
  spec.add_development_dependency "http_parser.rb"
26
31
  spec.add_development_dependency "docker-api"
32
+ spec.add_development_dependency "warning" if RUBY_VERSION >= "2.4"
27
33
  end
data/lib/down.rb CHANGED
@@ -6,12 +6,12 @@ require "down/net_http"
6
6
  module Down
7
7
  module_function
8
8
 
9
- def download(*args, &block)
10
- backend.download(*args, &block)
9
+ def download(*args, **options, &block)
10
+ backend.download(*args, **options, &block)
11
11
  end
12
12
 
13
- def open(*args, &block)
14
- backend.open(*args, &block)
13
+ def open(*args, **options, &block)
14
+ backend.open(*args, **options, &block)
15
15
  end
16
16
 
17
17
  # Allows setting a backend via a symbol or a downloader object.
data/lib/down/backend.rb CHANGED
@@ -9,12 +9,12 @@ require "fileutils"
9
9
 
10
10
  module Down
11
11
  class Backend
12
- def self.download(*args, &block)
13
- new.download(*args, &block)
12
+ def self.download(*args, **options, &block)
13
+ new.download(*args, **options, &block)
14
14
  end
15
15
 
16
- def self.open(*args, &block)
17
- new.open(*args, &block)
16
+ def self.open(*args, **options, &block)
17
+ new.open(*args, **options, &block)
18
18
  end
19
19
 
20
20
  private
@@ -36,6 +36,8 @@ module Down
36
36
  @rewindable = rewindable
37
37
  @buffer = nil
38
38
  @position = 0
39
+ @next_chunk = nil
40
+ @closed = false
39
41
 
40
42
  retrieve_chunk # fetch first chunk so that we know whether the file is empty
41
43
  end
@@ -63,7 +65,9 @@ module Down
63
65
  def read(length = nil, outbuf = nil)
64
66
  fail IOError, "closed stream" if closed?
65
67
 
66
- data = outbuf.to_s.clear.force_encoding(Encoding::BINARY)
68
+ data = outbuf.clear.force_encoding(Encoding::BINARY) if outbuf
69
+ data ||= "".b
70
+
67
71
  remaining_length = length
68
72
 
69
73
  until remaining_length == 0 || eof?
@@ -142,7 +146,8 @@ module Down
142
146
  # or the next chunk. This is useful when you don't care about the size of
143
147
  # chunks and you want to minimize string allocations.
144
148
  #
145
- # With `maxlen` argument returns maximum of that amount of bytes.
149
+ # With `maxlen` argument returns maximum of that amount of bytes (default
150
+ # is 16KB).
146
151
  #
147
152
  # With `outbuf` argument each call will return that same string object,
148
153
  # where the value is replaced with retrieved content.
@@ -154,7 +159,8 @@ module Down
154
159
  maxlen ||= 16*1024
155
160
 
156
161
  data = cache.read(maxlen, outbuf) if cache && !cache.eof?
157
- data ||= outbuf.to_s.clear
162
+ data ||= outbuf.clear.force_encoding(Encoding::BINARY) if outbuf
163
+ data ||= "".b
158
164
 
159
165
  return data if maxlen == 0
160
166
 
data/lib/down/errors.rb CHANGED
@@ -13,11 +13,14 @@ module Down
13
13
  # raised when the number of redirects was larger than the specified maximum
14
14
  class TooManyRedirects < Error; end
15
15
 
16
+ # raised when the requested resource has not been modified
17
+ class NotModified < Error; end
18
+
16
19
  # raised when response returned 4xx or 5xx response
17
20
  class ResponseError < Error
18
21
  attr_reader :response
19
22
 
20
- def initialize(message, response: nil)
23
+ def initialize(message, response = nil)
21
24
  super(message)
22
25
  @response = response
23
26
  end
data/lib/down/http.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen-string-literal: true
2
2
 
3
- gem "http", ">= 2.1.0", "< 5"
3
+ gem "http", ">= 2.1.0", "< 6"
4
4
 
5
5
  require "http"
6
6
 
@@ -12,7 +12,7 @@ module Down
12
12
  # Provides streaming downloads implemented with HTTP.rb.
13
13
  class Http < Backend
14
14
  # Initializes the backend with common defaults.
15
- def initialize(options = {}, &block)
15
+ def initialize(**options, &block)
16
16
  @method = options.delete(:method) || :get
17
17
  @client = HTTP
18
18
  .headers("User-Agent" => "Down/#{Down::VERSION}")
@@ -31,7 +31,7 @@ module Down
31
31
  content_length_proc.call(response.content_length) if content_length_proc && response.content_length
32
32
 
33
33
  if max_size && response.content_length && response.content_length > max_size
34
- raise Down::TooLarge, "file is too large (max is #{max_size/1024/1024}MB)"
34
+ raise Down::TooLarge, "file is too large (#{response.content_length/1024/1024}MB, max is #{max_size/1024/1024}MB)"
35
35
  end
36
36
 
37
37
  extname = File.extname(response.uri.path)
@@ -44,7 +44,7 @@ module Down
44
44
  progress_proc.call(tempfile.size) if progress_proc
45
45
 
46
46
  if max_size && tempfile.size > max_size
47
- raise Down::TooLarge, "file is too large (max is #{max_size/1024/1024}MB)"
47
+ raise Down::TooLarge, "file is too large (#{tempfile.size/1024/1024}MB, max is #{max_size/1024/1024}MB)"
48
48
  end
49
49
  end
50
50
 
@@ -106,7 +106,7 @@ module Down
106
106
 
107
107
  # Raises non-sucessful response as a Down::ResponseError.
108
108
  def response_error!(response)
109
- args = [response.status.to_s, response: response]
109
+ args = [response.status.to_s, response]
110
110
 
111
111
  case response.code
112
112
  when 404 then raise Down::NotFound.new(*args)
data/lib/down/net_http.rb CHANGED
@@ -12,27 +12,34 @@ require "fileutils"
12
12
  module Down
13
13
  # Provides streaming downloads implemented with Net::HTTP and open-uri.
14
14
  class NetHttp < Backend
15
+ URI_NORMALIZER = -> (url) do
16
+ addressable_uri = Addressable::URI.parse(url)
17
+ addressable_uri.normalize.to_s
18
+ end
19
+
15
20
  # Initializes the backend with common defaults.
16
- def initialize(options = {})
17
- @options = {
18
- "User-Agent" => "Down/#{Down::VERSION}",
19
- max_redirects: 2,
20
- open_timeout: 30,
21
- read_timeout: 30,
22
- }.merge(options)
21
+ def initialize(*args, **options)
22
+ @options = merge_options({
23
+ headers: { "User-Agent" => "Down/#{Down::VERSION}" },
24
+ max_redirects: 2,
25
+ open_timeout: 30,
26
+ read_timeout: 30,
27
+ uri_normalizer: URI_NORMALIZER,
28
+ }, *args, **options)
23
29
  end
24
30
 
25
31
  # Downloads a remote file to disk using open-uri. Accepts any open-uri
26
32
  # options, and a few more.
27
- def download(url, options = {})
28
- options = @options.merge(options)
33
+ def download(url, *args, **options)
34
+ options = merge_options(@options, *args, **options)
29
35
 
30
36
  max_size = options.delete(:max_size)
31
37
  max_redirects = options.delete(:max_redirects)
32
38
  progress_proc = options.delete(:progress_proc)
33
39
  content_length_proc = options.delete(:content_length_proc)
34
40
  destination = options.delete(:destination)
35
- headers = options.delete(:headers) || {}
41
+ headers = options.delete(:headers)
42
+ uri_normalizer = options.delete(:uri_normalizer)
36
43
 
37
44
  # Use open-uri's :content_lenth_proc or :progress_proc to raise an
38
45
  # exception early if the file is too large.
@@ -42,13 +49,13 @@ module Down
42
49
  open_uri_options = {
43
50
  content_length_proc: proc { |size|
44
51
  if size && max_size && size > max_size
45
- raise Down::TooLarge, "file is too large (max is #{max_size/1024/1024}MB)"
52
+ raise Down::TooLarge, "file is too large (#{size/1024/1024}MB, max is #{max_size/1024/1024}MB)"
46
53
  end
47
54
  content_length_proc.call(size) if content_length_proc
48
55
  },
49
56
  progress_proc: proc { |current_size|
50
57
  if max_size && current_size > max_size
51
- raise Down::TooLarge, "file is too large (max is #{max_size/1024/1024}MB)"
58
+ raise Down::TooLarge, "file is too large (#{current_size/1024/1024}MB, max is #{max_size/1024/1024}MB)"
52
59
  end
53
60
  progress_proc.call(current_size) if progress_proc
54
61
  },
@@ -74,7 +81,7 @@ module Down
74
81
  open_uri_options.merge!(options)
75
82
  open_uri_options.merge!(headers)
76
83
 
77
- uri = ensure_uri(addressable_normalize(url))
84
+ uri = ensure_uri(normalize_uri(url, uri_normalizer: uri_normalizer))
78
85
 
79
86
  # Handle basic authentication in the remote URL.
80
87
  if uri.user || uri.password
@@ -95,13 +102,17 @@ module Down
95
102
 
96
103
  # Starts retrieving the remote file using Net::HTTP and returns an IO-like
97
104
  # object which downloads the response body on-demand.
98
- def open(url, options = {})
99
- uri = ensure_uri(addressable_normalize(url))
100
- options = @options.merge(options)
105
+ def open(url, *args, **options)
106
+ options = merge_options(@options, *args, **options)
107
+
108
+ max_redirects = options.delete(:max_redirects)
109
+ uri_normalizer = options.delete(:uri_normalizer)
110
+
111
+ uri = ensure_uri(normalize_uri(url, uri_normalizer: uri_normalizer))
101
112
 
102
113
  # Create a Fiber that halts when response headers are received.
103
114
  request = Fiber.new do
104
- net_http_request(uri, options) do |response|
115
+ net_http_request(uri, options, follows_remaining: max_redirects) do |response|
105
116
  Fiber.yield response
106
117
  end
107
118
  end
@@ -131,7 +142,7 @@ module Down
131
142
  private
132
143
 
133
144
  # Calls open-uri's URI::HTTP#open method. Additionally handles redirects.
134
- def open_uri(uri, options, follows_remaining: 0)
145
+ def open_uri(uri, options, follows_remaining:)
135
146
  uri.open(options)
136
147
  rescue OpenURI::HTTPRedirect => exception
137
148
  raise Down::TooManyRedirects, "too many redirects" if follows_remaining == 0
@@ -186,7 +197,7 @@ module Down
186
197
  end
187
198
 
188
199
  # Makes a Net::HTTP request and follows redirects.
189
- def net_http_request(uri, options, follows_remaining: options.fetch(:max_redirects, 2), &block)
200
+ def net_http_request(uri, options, follows_remaining:, &block)
190
201
  http, request = create_net_http(uri, options)
191
202
 
192
203
  begin
@@ -205,7 +216,9 @@ module Down
205
216
  request_error!(exception)
206
217
  end
207
218
 
208
- if response.is_a?(Net::HTTPRedirection)
219
+ if response.is_a?(Net::HTTPNotModified)
220
+ raise Down::NotModified
221
+ elsif response.is_a?(Net::HTTPRedirection)
209
222
  raise Down::TooManyRedirects if follows_remaining == 0
210
223
 
211
224
  # fail if redirect URI is not a valid http or https URL
@@ -251,12 +264,13 @@ module Down
251
264
  http.read_timeout = options[:read_timeout] if options.key?(:read_timeout)
252
265
  http.open_timeout = options[:open_timeout] if options.key?(:open_timeout)
253
266
 
254
- headers = options.select { |key, value| key.is_a?(String) }
255
- headers.merge!(options[:headers]) if options[:headers]
267
+ headers = options[:headers].to_h
256
268
  headers["Accept-Encoding"] = "" # Net::HTTP's inflater causes FiberErrors
257
269
 
258
270
  get = Net::HTTP::Get.new(uri.request_uri, headers)
259
- get.basic_auth(uri.user, uri.password) if uri.user || uri.password
271
+
272
+ user, password = options[:http_basic_authentication] || [uri.user, uri.password]
273
+ get.basic_auth(user, password) if user || password
260
274
 
261
275
  [http, get]
262
276
  end
@@ -284,11 +298,10 @@ module Down
284
298
  end
285
299
 
286
300
  # Makes sure that the URL is properly encoded.
287
- def addressable_normalize(url)
301
+ def normalize_uri(url, uri_normalizer:)
288
302
  URI(url)
289
303
  rescue URI::InvalidURIError
290
- addressable_uri = Addressable::URI.parse(url)
291
- addressable_uri.normalize.to_s
304
+ uri_normalizer.call(url)
292
305
  end
293
306
 
294
307
  # When open-uri raises an exception, it doesn't expose the response object.
@@ -297,7 +310,11 @@ module Down
297
310
  def rebuild_response_from_open_uri_exception(exception)
298
311
  code, message = exception.io.status
299
312
 
300
- response_class = Net::HTTPResponse::CODE_TO_OBJ.fetch(code)
313
+ response_class = Net::HTTPResponse::CODE_TO_OBJ.fetch(code) do |code|
314
+ Net::HTTPResponse::CODE_CLASS_TO_OBJ.fetch(code[0]) do
315
+ Net::HTTPUnknownResponse
316
+ end
317
+ end
301
318
  response = response_class.new(nil, code, message)
302
319
 
303
320
  exception.io.metas.each do |name, values|
@@ -312,7 +329,7 @@ module Down
312
329
  code = response.code.to_i
313
330
  message = response.message.split(" ").map(&:capitalize).join(" ")
314
331
 
315
- args = ["#{code} #{message}", response: response]
332
+ args = ["#{code} #{message}", response]
316
333
 
317
334
  case response.code.to_i
318
335
  when 404 then raise Down::NotFound.new(*args)
@@ -338,6 +355,24 @@ module Down
338
355
  end
339
356
  end
340
357
 
358
+ # Merge default and ad-hoc options, merging nested headers.
359
+ def merge_options(options, headers = {}, **new_options)
360
+ # Deprecate passing headers as top-level options, taking into account
361
+ # that Ruby 2.7+ accepts kwargs with string keys.
362
+ if headers.any?
363
+ warn %([Down::NetHttp] Passing headers as top-level options has been deprecated, use the :headers option instead, e.g: `Down::NetHttp.download(headers: { "Key" => "Value", ... }, ...)`)
364
+ new_options[:headers] = headers
365
+ elsif new_options.any? { |key, value| key.is_a?(String) }
366
+ warn %([Down::NetHttp] Passing headers as top-level options has been deprecated, use the :headers option instead, e.g: `Down::NetHttp.download(headers: { "Key" => "Value", ... }, ...)`)
367
+ new_options[:headers] = new_options.select { |key, value| key.is_a?(String) }
368
+ new_options.reject! { |key, value| key.is_a?(String) }
369
+ end
370
+
371
+ options.merge(new_options) do |key, value1, value2|
372
+ key == :headers ? value1.merge(value2) : value2
373
+ end
374
+ end
375
+
341
376
  # Defines some additional attributes for the returned Tempfile (on top of what
342
377
  # OpenURI::Meta already defines).
343
378
  module DownloadedFile
data/lib/down/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  module Down
4
- VERSION = "5.0.1"
4
+ VERSION = "5.2.2"
5
5
  end
data/lib/down/wget.rb CHANGED
@@ -35,7 +35,7 @@ module Down
35
35
  content_length_proc.call(io.size) if content_length_proc && io.size
36
36
 
37
37
  if max_size && io.size && io.size > max_size
38
- raise Down::TooLarge, "file is too large (max is #{max_size/1024/1024}MB)"
38
+ raise Down::TooLarge, "file is too large (#{io.size/1024/1024}MB, max is #{max_size/1024/1024}MB)"
39
39
  end
40
40
 
41
41
  extname = File.extname(URI(url).path)
@@ -49,7 +49,7 @@ module Down
49
49
  progress_proc.call(tempfile.size) if progress_proc
50
50
 
51
51
  if max_size && tempfile.size > max_size
52
- raise Down::TooLarge, "file is too large (max is #{max_size/1024/1024}MB)"
52
+ raise Down::TooLarge, "file is too large (#{tempfile.size/1024/1024}MB, max is #{max_size/1024/1024}MB)"
53
53
  end
54
54
  end
55
55
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: down
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.1
4
+ version: 5.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Janko Marohnić
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-20 00:00:00.000000000 Z
11
+ date: 2021-05-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '4.0'
75
+ version: '5.0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '4.0'
82
+ version: '5.0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: posix-spawn
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -122,7 +122,21 @@ dependencies:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
- description:
125
+ - !ruby/object:Gem::Dependency
126
+ name: warning
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description:
126
140
  email:
127
141
  - janko.marohnic@gmail.com
128
142
  executables: []
@@ -146,7 +160,7 @@ homepage: https://github.com/janko/down
146
160
  licenses:
147
161
  - MIT
148
162
  metadata: {}
149
- post_install_message:
163
+ post_install_message:
150
164
  rdoc_options: []
151
165
  require_paths:
152
166
  - lib
@@ -154,15 +168,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
154
168
  requirements:
155
169
  - - ">="
156
170
  - !ruby/object:Gem::Version
157
- version: '2.1'
171
+ version: '2.3'
158
172
  required_rubygems_version: !ruby/object:Gem::Requirement
159
173
  requirements:
160
174
  - - ">="
161
175
  - !ruby/object:Gem::Version
162
176
  version: '0'
163
177
  requirements: []
164
- rubygems_version: 3.1.1
165
- signing_key:
178
+ rubygems_version: 3.2.15
179
+ signing_key:
166
180
  specification_version: 4
167
181
  summary: Robust streaming downloads using Net::HTTP, HTTP.rb or wget.
168
182
  test_files: []