diff --git a/google-apis-core/lib/google/apis/core/download.rb b/google-apis-core/lib/google/apis/core/download.rb index e947b6f5374..282ea15c905 100644 --- a/google-apis-core/lib/google/apis/core/download.rb +++ b/google-apis-core/lib/google/apis/core/download.rb @@ -81,7 +81,10 @@ def execute_once(client, &block) http_res = client.get(url.to_s, query, request_header) do |request| request.options.on_data = proc do |chunk, _size, res| - status = res.status.to_i + # The on_data callback is only invoked on a successful response. + # Some Faraday adapters (e.g. Typhoeus) may not provide a response + # object in the callback, so we default to a 200 OK status. + status = res ? res.status.to_i : 200 next if chunk.nil? || (status >= 300 && status < 400) # HTTP 206 is Partial Content diff --git a/google-apis-core/lib/google/apis/core/storage_download.rb b/google-apis-core/lib/google/apis/core/storage_download.rb index 3298f063d9e..476999c4073 100644 --- a/google-apis-core/lib/google/apis/core/storage_download.rb +++ b/google-apis-core/lib/google/apis/core/storage_download.rb @@ -48,7 +48,10 @@ def execute_once(client, &block) http_res = client.get(url.to_s, query, request_header) do |request| request.options.on_data = proc do |chunk, _size, res| - status = res.status.to_i + # The on_data callback is only invoked on a successful response. + # Some Faraday adapters (e.g. Typhoeus) may not provide a response + # object in the callback, so we default to a 200 OK status. + status = res ? res.status.to_i : 200 next if chunk.nil? || (status >= 300 && status < 400) download_offset ||= (status == 206 ? @offset : 0) diff --git a/google-apis-core/spec/google/apis/core/download_spec.rb b/google-apis-core/spec/google/apis/core/download_spec.rb index c50c18c2338..dc8b5044146 100644 --- a/google-apis-core/spec/google/apis/core/download_spec.rb +++ b/google-apis-core/spec/google/apis/core/download_spec.rb @@ -136,6 +136,27 @@ def write(data) end end + context 'with streaming response' do + let(:dest) { Tempfile.new('test') } + let(:received) do + command.execute(client) + dest.rewind + dest.read + end + + it 'should receive content' do + response = Faraday::Response.new(status: 200, body: 'Hello world') + expect(client).to receive(:get) do |_url, _params, _headers, &block| + request = Faraday::Request.new + request.options = Faraday::RequestOptions.new + block.call(request) + request.options.on_data.call('Hello world', 11, nil) + response + end + expect(received).to eql 'Hello world' + end + end + context 'with pathname destination' do let(:dest) { Pathname.new(File.join(Dir.mktmpdir, 'test-path.txt')) } let(:received) do diff --git a/google-apis-core/spec/google/apis/core/storage_download_spec.rb b/google-apis-core/spec/google/apis/core/storage_download_spec.rb index 92b1e482048..2e28587a781 100644 --- a/google-apis-core/spec/google/apis/core/storage_download_spec.rb +++ b/google-apis-core/spec/google/apis/core/storage_download_spec.rb @@ -135,4 +135,25 @@ def write(data) end end end + + context 'with streaming response' do + let(:dest) { Tempfile.new('test') } + let(:received) do + command.execute(client) + dest.rewind + dest.read + end + + it 'should receive content' do + response = Faraday::Response.new(status: 200, body: 'Hello world') + expect(client).to receive(:get) do |_url, _params, _headers, &block| + request = Faraday::Request.new + request.options = Faraday::RequestOptions.new + block.call(request) + request.options.on_data.call('Hello world', 11, nil) + response + end + expect(received).to eql 'Hello world' + end + end end