lib/remote_io.rb
def request_range(range)
    # We use a GET and not a HEAD request followed by a GET because
    # S3 does not allow HEAD requests if you only presigned your URL for GETs, so we
    # combine the first GET of a segment and retrieving the size of the resource
    response = Faraday.get(@uri, nil, range: 'bytes=%d-%d' % [range.begin, range.end])

    case response.status
    when 200, 206
      # Figure out of the server supports content ranges, if it doesn't we have no
      # business working with that server
      range_header = response.headers['Content-Range']
      raise InvalidRequest.new(response.status, "No range support at #{@uri}") unless range_header

      # "Content-Range: bytes 0-0/307404381" is how the response header is structured
      size = range_header[/\/(\d+)$/, 1].to_i

      # S3 returns 200 when you request a Range that is fully satisfied by the entire object,
      # we take that into account here. For other servers, 206 is the expected response code.
      # Also, if we request a _larger_ range than what can be satisfied by the server,
      # the response is going to only contain what _can_ be sent and the status is also going
      # to be 206
      return [size, response.body]
    when 416
      # We return `nil` if we tried to read past the end of the IO,
      # which satisfies the Ruby IO convention. The caller should deal with `nil` being the result of a read()
      # S3 will also handily _not_ supply us with the Content-Range of the actual resource, so we
      # cannot hint size with this response - at lease not when working with S3
      return
    when 500..599
      Measurometer.increment_counter('format_parser.RemoteIO.upstream50x_errors', 1)
      raise IntermittentFailure.new(response.status, "Server at #{@uri} replied with a #{response.status} and we might want to retry")
    else
      Measurometer.increment_counter('format_parser.RemoteIO.invalid_request_errors', 1)
      raise InvalidRequest.new(response.status, "Server at #{@uri} replied with a #{response.status} and refused our request")
    end
  end
# Only used internally when reading the remote file
#
# @param range[Range] the HTTP range of data to fetch from remote
# @return [String] the response body of the ranged request
Only used internally when reading the remote file
Only used internally when reading the remote file
def request_range(range)
    response = Faraday.get(@uri, nil, range: 'bytes=%d-%d' % [range.begin, range.end])
    case response.status
    when 200, 206
      range_header = response.headers['Content-Range']
      raise InvalidRequest.new(response.status, "No range support at #{@uri}") unless range_header
      size = range_header[/\/(\d+)$/, 1].to_i
      return [size, response.body]
    when 416
      return
    when 500..599
      Measurometer.increment_counter('format_parser.RemoteIO.upstream50x_errors', 1)
      raise IntermittentFailure.new(response.status, "Server at #{@uri} replied with a #{response.status} and we might want to retry")
    else
      Measurometer.increment_counter('format_parser.RemoteIO.invalid_request_errors', 1)
      raise InvalidRequest.new(response.status, "Server at #{@uri} replied with a #{response.status} and refused our request")
    end
  end
def request_range ( range ) response = Faraday . get ( @uri , nil , range : 'bytes=%d-%d' % [ range . begin , range . end ] ) case response . status when 200 , 206 range_header = response . headers [ 'Content-Range' ] raise InvalidRequest . new ( response . status , "No range support at #{@uri}" ) unless range_header size = range_header [ / \/ ( \d +)$ / , 1 ] . to_i return [ size , response . body ] when 416 return when 500 .. 599 Measurometer . increment_counter ( 'format_parser.RemoteIO.upstream50x_errors' , 1 ) raise IntermittentFailure . new ( response . status , "Server at #{@uri} replied with a #{response.status} and we might want to retry" ) else Measurometer . increment_counter ( 'format_parser.RemoteIO.invalid_request_errors' , 1 ) raise InvalidRequest . new ( response . status , "Server at #{@uri} replied with a #{response.status} and refused our request" ) end end
Only used internally when reading the remote file
Only used internally when reading the remote file
# We use a GET and not a HEAD request followed by a GET because # S3 does not allow HEAD requests if you only presigned your URL for GETs, so we # combine the first GET of a segment and retrieving the size of the resource # Figure out of the server supports content ranges, if it doesn't we have no # business working with that server # "Content-Range: bytes 0-0/307404381" is how the response header is structured # S3 returns 200 when you request a Range that is fully satisfied by the entire object, # we take that into account here. For other servers, 206 is the expected response code. # Also, if we request a _larger_ range than what can be satisfied by the server, # the response is going to only contain what _can_ be sent and the status is also going # to be 206 # We return `nil` if we tried to read past the end of the IO, # which satisfies the Ruby IO convention. The caller should deal with `nil` being the result of a read() # S3 will also handily _not_ supply us with the Content-Range of the actual resource, so we # cannot hint size with this response - at lease not when working with S3
the response body of the ranged request
the response body of the ranged request
String
range
the HTTP range of data to fetch from remote
the HTTP range of data to fetch from remote