Class: Down::Http

Inherits:
Backend show all
Defined in:
lib/down/http.rb

Overview

Provides streaming downloads implemented with HTTP.rb.

Defined Under Namespace

Modules: DownloadedFile

Instance Method Summary collapse

Methods inherited from Backend

download, open

Constructor Details

#initialize(**options, &block) ⇒ Http

Initializes the backend with common defaults.



15
16
17
18
19
20
21
22
23
24
# File 'lib/down/http.rb', line 15

def initialize(**options, &block)
  @method = options.delete(:method) || :get
  @client = HTTP
    .headers("User-Agent" => "Down/#{Down::VERSION}")
    .follow(max_hops: 2)
    .timeout(connect: 30, write: 30, read: 30)

  @client = HTTP::Client.new(@client.default_options.merge(options)) if options.any?
  @client = block.call(@client) if block
end

Instance Method Details

#download(url, max_size: nil, progress_proc: nil, content_length_proc: nil, destination: nil, extension: nil, **options, &block) ⇒ Object

Downlods the remote file to disk. Accepts HTTP.rb options via a hash or a block, and some additional options as well.



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/down/http.rb', line 28

def download(url, max_size: nil, progress_proc: nil, content_length_proc: nil, destination: nil, extension: nil, **options, &block)
  response = request(url, **options, &block)

  content_length_proc.call(response.content_length) if content_length_proc && response.content_length

  if max_size && response.content_length && response.content_length > max_size
    raise Down::TooLarge, "file is too large (#{response.content_length/1024/1024}MB, max is #{max_size/1024/1024}MB)"
  end

  extname  = extension ? ".#{extension}" : File.extname(response.uri.path)
  tempfile = Tempfile.new(["down-http", extname], binmode: true)

  stream_body(response) do |chunk|
    tempfile.write(chunk)
    chunk.clear # deallocate string

    progress_proc.call(tempfile.size) if progress_proc

    if max_size && tempfile.size > max_size
      raise Down::TooLarge, "file is too large (#{tempfile.size/1024/1024}MB, max is #{max_size/1024/1024}MB)"
    end
  end

  tempfile.open # flush written content

  tempfile.extend Down::Http::DownloadedFile
  tempfile.url     = response.uri.to_s
  tempfile.headers = normalize_headers(response.headers.to_h)

  download_result(tempfile, destination)
rescue
  tempfile.close! if tempfile
  raise
end

#open(url, rewindable: true, **options, &block) ⇒ Object

Starts retrieving the remote file and returns an IO-like object which downloads the response body on-demand. Accepts HTTP.rb options via a hash or a block.



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/down/http.rb', line 66

def open(url, rewindable: true, **options, &block)
  response = request(url, **options, &block)

  Down::ChunkedIO.new(
    chunks:     enum_for(:stream_body, response),
    size:       response.content_length,
    encoding:   response.content_type.charset,
    rewindable: rewindable,
    data:       {
      status:   response.code,
      headers:  normalize_headers(response.headers.to_h),
      response: response
    },
  )
end