Module: Philiprehberger::HeaderKit::Range

Defined in:
lib/philiprehberger/header_kit/range.rb

Overview

Parses and builds the HTTP Range request header (RFC 7233 §3.1).

Format: ‘<unit>=<start>-<end>[, <start>-<end>]*` Supports byte ranges, suffix ranges (`-N`), and open-ended ranges (`N-`).

Class Method Summary collapse

Class Method Details

.build(unit, ranges) ⇒ String

Build a Range header value.

Examples:

build('bytes', [{ first: 0, last: 499 }])           # => "bytes=0-499"
build('bytes', [[0, 499], [500, nil]])              # => "bytes=0-499, 500-"
build('bytes', [(0..99), { first: nil, last: 50 }]) # => "bytes=0-99, -50"

Parameters:

  • unit (String)

    the range unit (e.g. ‘bytes’)

  • ranges (Array<Hash, Array, Range>)

    each as ‘{ first:, last: }`, a `[first, last]` array, or a Ruby `Range` (inclusive)

Returns:

  • (String)

    formatted Range header



50
51
52
53
54
# File 'lib/philiprehberger/header_kit/range.rb', line 50

def build(unit, ranges)
  list = ranges.is_a?(Array) ? ranges : [ranges]
  formatted = list.map { |r| format_range(r) }
  "#{unit}=#{formatted.join(', ')}"
end

.parse(header) ⇒ Hash{Symbol => Object}?

Parse a Range header value.

Examples:

parse('bytes=0-499')        # => { unit: 'bytes', ranges: [{ first: 0, last: 499 }] }
parse('bytes=500-')         # => { unit: 'bytes', ranges: [{ first: 500, last: nil }] }
parse('bytes=-500')         # => { unit: 'bytes', ranges: [{ first: nil, last: 500 }] }
parse('bytes=0-99, 200-')   # => { unit: 'bytes', ranges: [{ first: 0, last: 99 }, { first: 200, last: nil }] }

Parameters:

  • header (String, nil)

    the raw header value

Returns:

  • (Hash{Symbol => Object}, nil)

    hash with :unit (String) and :ranges (Array of Hash with :first/:last keys, where either may be nil for open-ended), or nil for nil/blank/invalid input



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/philiprehberger/header_kit/range.rb', line 23

def parse(header)
  return nil if header.nil?

  header = header.to_s.strip
  return nil if header.empty?

  unit, _, spec = header.partition('=')
  unit = unit.strip
  spec = spec.strip
  return nil if unit.empty? || spec.empty?

  ranges = spec.split(',').map { |part| parse_range(part.strip) }
  return nil if ranges.any?(&:nil?)

  { unit: unit, ranges: ranges }
end