Rewind output stream if requesting partial content but get the full media body instead

This commit is contained in:
Steve Bazyl 2016-04-22 14:30:30 -07:00
parent 0bb3352496
commit 0155b81771
2 changed files with 23 additions and 2 deletions

View File

@ -67,12 +67,21 @@ module Google
def execute_once(client, &block) def execute_once(client, &block)
client.get(@download_url || url) do |req| client.get(@download_url || url) do |req|
apply_request_options(req) apply_request_options(req)
check_if_rewind_needed = false
if @offset > 0 if @offset > 0
logger.debug { sprintf('Resuming download from offset %d', @offset) } logger.debug { sprintf('Resuming download from offset %d', @offset) }
req.header[RANGE_HEADER] = sprintf('bytes=%d-', @offset) req.header[RANGE_HEADER] = sprintf('bytes=%d-', @offset)
check_if_rewind_needed = true
end end
req.on_body(200, 201) do |res, chunk| req.on_body(200, 201, 206) do |res, chunk|
check_status(res.status_code, chunk) unless res.status_code.nil? check_status(res.status_code, chunk) unless res.status_code.nil?
if check_if_rewind_needed && res.status_code != 206
# Oh no! Requested a chunk, but received the entire content
# Attempt to rewind the stream
@download_io.rewind
check_if_rewind_needed = false
end
logger.debug { sprintf('Writing chunk (%d bytes)', chunk.length) } logger.debug { sprintf('Writing chunk (%d bytes)', chunk.length) }
@offset += chunk.length @offset += chunk.length
@download_io.write(chunk) @download_io.write(chunk)

View File

@ -52,7 +52,19 @@ RSpec.describe Google::Apis::Core::DownloadCommand do
before(:example) do before(:example) do
stub_request(:get, 'https://www.googleapis.com/zoo/animals') stub_request(:get, 'https://www.googleapis.com/zoo/animals')
.to_return(body: ['Hello ', Timeout::Error]) .to_return(body: ['Hello ', Timeout::Error])
.to_return(body: 'world') .to_return(status: [206, 'Partial content'], body: 'world')
end
it 'should receive entire content' do
expect(received).to eql('Hello world')
end
end
context 'with disconnects and no partial response' do
before(:example) do
stub_request(:get, 'https://www.googleapis.com/zoo/animals')
.to_return(body: ['Hello ', Timeout::Error])
.to_return(body: 'Hello world')
end end
it 'should receive entire content' do it 'should receive entire content' do