Class: IntervalResponse::Multi

Inherits:
Abstract
  • Object
show all
Defined in:
lib/interval_response/multi.rb

Constant Summary collapse

ALPHABET =
('0'..'9').to_a + ('a'..'z').to_a + ('A'..'Z').to_a

Instance Method Summary collapse

Methods inherited from Abstract

#etag, #to_rack_response_triplet

Constructor Details

#initialize(interval_sequence, http_ranges) ⇒ Multi

Returns a new instance of Multi.

Parameters:

  • http_ranges (Array<Range>)


5
6
7
8
9
10
11
12
13
# File 'lib/interval_response/multi.rb', line 5

def initialize(interval_sequence, http_ranges)
  @interval_sequence = interval_sequence
  @http_ranges = http_ranges
  # RFC1521 says that a boundary "must be no longer than 70 characters,
  # not counting the two leading hyphens".
  # Standard Ruby randomness is biased but it doesn't matter much for us (we do not need to
  # be extremely secure here)
  @boundary = ALPHABET.sample(24).join
end

Instance Method Details

#content_lengthObject



31
32
33
34
35
36
37
38
39
# File 'lib/interval_response/multi.rb', line 31

def content_length
  # The Content-Length of a multipart response includes the length
  # of all the ranges of the resource, but also the lengths of the
  # multipart part headers - which we need to precompute. To do it
  # we need to run through all of our ranges and output some strings,
  # and if a lot of ranges are involved this can get expensive. So
  # memoize the envelope size (it never changes between calls)
  @envelope_size ||= compute_envelope_size
end

#eachObject



15
16
17
18
19
20
21
22
23
24
25
# File 'lib/interval_response/multi.rb', line 15

def each
  # serve the part of the interval map
  @http_ranges.each_with_index do |http_range, range_i|
    part_header = part_header(range_i, http_range)
    entire_header_range = 0..(part_header.bytesize - 1)
    yield(part_header, entire_header_range)
    @interval_sequence.each_in_range(http_range) do |segment, range_in_segment|
      yield(segment, range_in_segment)
    end
  end
end

#headersObject



41
42
43
44
45
46
47
48
# File 'lib/interval_response/multi.rb', line 41

def headers
  {
    'Accept-Ranges' => 'bytes',
    'Content-Length' => content_length.to_s,
    'Content-Type' => "multipart/byte-ranges; boundary=#{@boundary}",
    'ETag' => etag,
  }
end

#multiple_ranges?Boolean

Returns:

  • (Boolean)


54
55
56
# File 'lib/interval_response/multi.rb', line 54

def multiple_ranges?
  true
end

#satisfied_with_first_interval?Boolean

Returns:

  • (Boolean)


50
51
52
# File 'lib/interval_response/multi.rb', line 50

def satisfied_with_first_interval?
  @interval_sequence.first_interval_only?(*@http_ranges)
end

#status_codeObject



27
28
29
# File 'lib/interval_response/multi.rb', line 27

def status_code
  206
end