google-apis-core 0.18.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/OVERVIEW.md +18 -0
- data/lib/google/apis/core/base_service.rb +20 -37
- data/lib/google/apis/core/batch.rb +7 -7
- data/lib/google/apis/core/download.rb +24 -23
- data/lib/google/apis/core/faraday_integration.rb +47 -0
- data/lib/google/apis/core/http_command.rb +23 -28
- data/lib/google/apis/core/storage_download.rb +28 -25
- data/lib/google/apis/core/storage_upload.rb +19 -21
- data/lib/google/apis/core/upload.rb +16 -19
- data/lib/google/apis/core/version.rb +1 -1
- data/lib/google/apis/options.rb +1 -1
- metadata +25 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2e4864fdbdd96f55fa077d183ac6c25f87d16509b48bd270803c73f81d4fa47b
|
4
|
+
data.tar.gz: 869598753c71741fcd2a4f474b464a609d6fcb2b6513c9c87d75ff1365192d07
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4bfce12bdbf8dd48e4856b77902d7fef1343ae940400e56090b1d946ed26e786b1f39ae17f3aa60dfc63e3594411c48eb5711957ad7a0f55c136fab03e45edb8
|
7
|
+
data.tar.gz: 21c7758ca4994eef7b077b19b10affcc112a909834f3b7dc5b346df42712ea3d68cccabf8131c869410ce3091f679509f39f834d5f05fbb31ea8c14ec40d8a45
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# Release History
|
2
2
|
|
3
|
+
### 1.0.0 (2025-08-03)
|
4
|
+
|
5
|
+
This is a major release that replaces the underlying httpclient library with Faraday ([#23524](https://github.com/googleapis/google-api-ruby-client/issues/23524)). This will ensure the client libraries are on a more stable and better maintained foundation moving forward.
|
6
|
+
|
7
|
+
For most users, this change should be transparent. However, if your application depends on the httpclient interfaces, you can retain compatibility with httpclient by pinning the `google-apis-core` gem to `~> 0.18` in your Gemfile. Httpclient-based versions of this gem will remain on the 0.x release train, while Faraday-based versions will occupy the 1.x release train. We will push critical fixes and security updates to both branches for one year until August 2026, but new feature work will take place only on the 1.x branch.
|
8
|
+
|
3
9
|
### 0.18.0 (2025-05-22)
|
4
10
|
|
5
11
|
#### Features
|
data/OVERVIEW.md
CHANGED
@@ -4,6 +4,24 @@ This library includes common base classes and dependencies used by legacy REST
|
|
4
4
|
clients for Google APIs. It is used by client libraries, but you should not
|
5
5
|
need to install it by itself.
|
6
6
|
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
In most cases, this library is installed automatically as a dependency of
|
10
|
+
another library. For example, if you install the
|
11
|
+
[google-apis-drive_v3](https://rubygems.org/gems/google-apis-drive_v3) client
|
12
|
+
library, it will bring in the latest `google-apis-core` as a dependency. Thus,
|
13
|
+
in most cases, you do not need to add `google-apis-core` to your Gemfile
|
14
|
+
directly.
|
15
|
+
|
16
|
+
Earlier (0.x) versions of this library utilized the legacy
|
17
|
+
[httpclient](https://rubygems.org/gems/httpclient) gem and made some of its
|
18
|
+
interfaces available for advanced use cases. Version 1.0 and later of this
|
19
|
+
library replaced httpclient with [faraday](https://rubygems.org/gems/faraday).
|
20
|
+
If your application makes use of the httpclient interfaces (this is rare), you
|
21
|
+
should pin `google-apis-core` to a 0.x version in your Gemfile. For example:
|
22
|
+
|
23
|
+
gem "google-apis-core", "~> 0.18"
|
24
|
+
|
7
25
|
## Documentation
|
8
26
|
|
9
27
|
More detailed descriptions of the Google legacy REST clients are available in two documents.
|
@@ -18,13 +18,13 @@ require 'google/apis'
|
|
18
18
|
require 'google/apis/core/version'
|
19
19
|
require 'google/apis/core/api_command'
|
20
20
|
require 'google/apis/core/batch'
|
21
|
+
require 'google/apis/core/faraday_integration'
|
21
22
|
require 'google/apis/core/upload'
|
22
23
|
require 'google/apis/core/storage_upload'
|
23
24
|
require 'google/apis/core/download'
|
24
25
|
require 'google/apis/core/storage_download'
|
25
26
|
require 'google/apis/options'
|
26
27
|
require 'googleauth'
|
27
|
-
require 'httpclient'
|
28
28
|
|
29
29
|
module Google
|
30
30
|
module Apis
|
@@ -149,8 +149,8 @@ module Google
|
|
149
149
|
# @return [Addressable::URI]
|
150
150
|
attr_accessor :batch_path
|
151
151
|
|
152
|
-
# HTTP
|
153
|
-
# @return [
|
152
|
+
# Faraday HTTP connection
|
153
|
+
# @return [Faraday::Connection]
|
154
154
|
attr_writer :client
|
155
155
|
|
156
156
|
# General settings
|
@@ -263,8 +263,8 @@ module Google
|
|
263
263
|
batch_command.execute(client)
|
264
264
|
end
|
265
265
|
|
266
|
-
# Get the current HTTP
|
267
|
-
# @return [
|
266
|
+
# Get the current HTTP connection
|
267
|
+
# @return [Faraday::Connection]
|
268
268
|
def client
|
269
269
|
@client ||= new_client
|
270
270
|
end
|
@@ -376,7 +376,7 @@ module Google
|
|
376
376
|
command = make_storage_upload_command(:delete, 'b/{bucket}/o', options)
|
377
377
|
command.upload_id = upload_id
|
378
378
|
command.params['bucket'] = bucket unless bucket.nil?
|
379
|
-
command.delete_upload =
|
379
|
+
command.delete_upload = true
|
380
380
|
execute_or_queue_command(command)
|
381
381
|
end
|
382
382
|
|
@@ -542,39 +542,22 @@ module Google
|
|
542
542
|
Thread.current[:google_api_batch_service] = nil
|
543
543
|
end
|
544
544
|
|
545
|
-
# Create a new HTTP
|
546
|
-
# @return [
|
545
|
+
# Create a new HTTP connection
|
546
|
+
# @return [Faraday::Connection]
|
547
547
|
def new_client
|
548
|
-
|
549
|
-
|
550
|
-
if client_options.
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
if client_options.read_timeout_sec
|
561
|
-
client.receive_timeout = client_options.read_timeout_sec
|
548
|
+
options = {}
|
549
|
+
request_options = {params_encoder: Faraday::FlatParamsEncoder}
|
550
|
+
options[:proxy] = {uri: client_options.proxy_url} if client_options.proxy_url
|
551
|
+
request_options[:open_timeout] = client_options.open_timeout_sec if client_options.open_timeout_sec
|
552
|
+
request_options[:read_timeout] = client_options.read_timeout_sec if client_options.read_timeout_sec
|
553
|
+
request_options[:write_timeout] = client_options.send_timeout_sec if client_options.send_timeout_sec
|
554
|
+
options[:request] = request_options unless request_options.empty?
|
555
|
+
options[:headers] = { 'User-Agent' => user_agent }
|
556
|
+
|
557
|
+
Faraday.new options do |faraday|
|
558
|
+
faraday.response :logger, Google::Apis.logger if client_options.log_http_requests
|
559
|
+
faraday.response :follow_redirects_google_apis_core, limit: 5
|
562
560
|
end
|
563
|
-
|
564
|
-
if client_options.send_timeout_sec
|
565
|
-
client.send_timeout = client_options.send_timeout_sec
|
566
|
-
end
|
567
|
-
|
568
|
-
client.follow_redirect_count = 5
|
569
|
-
client.default_header = { 'User-Agent' => user_agent }
|
570
|
-
|
571
|
-
client.debug_dev = logger if client_options.log_http_requests
|
572
|
-
|
573
|
-
# Make HttpClient use system default root CA path
|
574
|
-
# https://github.com/nahi/httpclient/issues/445
|
575
|
-
client.ssl_config.clear_cert_store
|
576
|
-
client.ssl_config.cert_store.set_default_paths
|
577
|
-
client
|
578
561
|
end
|
579
562
|
|
580
563
|
|
@@ -82,7 +82,7 @@ module Google
|
|
82
82
|
parts.each_index do |index|
|
83
83
|
response = deserializer.to_http_response(parts[index])
|
84
84
|
outer_header = response.shift
|
85
|
-
call_id = header_to_id(outer_header['Content-ID'].first) || index
|
85
|
+
call_id = header_to_id(Array(outer_header['Content-ID']).first) || index
|
86
86
|
call, callback = @calls[call_id]
|
87
87
|
begin
|
88
88
|
result = call.process_response(*response) unless call.nil?
|
@@ -211,14 +211,14 @@ module Google
|
|
211
211
|
|
212
212
|
protected
|
213
213
|
|
214
|
-
# Auxiliary method to split the
|
214
|
+
# Auxiliary method to split the headers from the body in an HTTP response.
|
215
215
|
#
|
216
216
|
# @param [String] response
|
217
217
|
# the response to parse.
|
218
|
-
# @return [Array<(
|
219
|
-
# the
|
218
|
+
# @return [Array<(Hash{String=>Array<String>}, String)>]
|
219
|
+
# the headers and the body, separately.
|
220
220
|
def split_header_and_body(response)
|
221
|
-
|
221
|
+
headers = {}
|
222
222
|
payload = response.lstrip
|
223
223
|
while payload
|
224
224
|
line, payload = payload.split(/\n/, 2)
|
@@ -226,9 +226,9 @@ module Google
|
|
226
226
|
break if line.empty?
|
227
227
|
match = /\A([^:]+):\s*/.match(line)
|
228
228
|
fail BatchError, sprintf('Invalid header line in response: %s', line) if match.nil?
|
229
|
-
|
229
|
+
(headers[match[1]] ||= []) << match.post_match
|
230
230
|
end
|
231
|
-
[
|
231
|
+
[headers, payload]
|
232
232
|
end
|
233
233
|
end
|
234
234
|
end
|
@@ -23,6 +23,8 @@ module Google
|
|
23
23
|
# Streaming/resumable media download support
|
24
24
|
class DownloadCommand < ApiCommand
|
25
25
|
RANGE_HEADER = 'Range'
|
26
|
+
|
27
|
+
# @deprecated No longer used
|
26
28
|
OK_STATUS = [200, 201, 206]
|
27
29
|
|
28
30
|
# File or IO to write content to
|
@@ -61,8 +63,7 @@ module Google
|
|
61
63
|
# of file content.
|
62
64
|
#
|
63
65
|
# @private
|
64
|
-
# @param [
|
65
|
-
# HTTP client
|
66
|
+
# @param [Faraday::Connection] client Faraday connection
|
66
67
|
# @yield [result, err] Result or error if block supplied
|
67
68
|
# @return [Object]
|
68
69
|
# @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
|
@@ -78,39 +79,39 @@ module Google
|
|
78
79
|
request_header[RANGE_HEADER] = sprintf('bytes=%d-', @offset)
|
79
80
|
end
|
80
81
|
|
81
|
-
http_res = client.get(url.to_s,
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
status = res.http_header.status_code.to_i
|
86
|
-
next unless OK_STATUS.include?(status)
|
82
|
+
http_res = client.get(url.to_s, query, request_header) do |request|
|
83
|
+
request.options.on_data = proc do |chunk, _size, res|
|
84
|
+
status = res.status.to_i
|
85
|
+
next if chunk.nil? || (status >= 300 && status < 400)
|
87
86
|
|
88
|
-
|
89
|
-
|
87
|
+
# HTTP 206 is Partial Content
|
88
|
+
download_offset ||= (status == 206 ? @offset : 0)
|
89
|
+
download_offset += chunk.bytesize
|
90
90
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
91
|
+
if download_offset - chunk.bytesize == @offset
|
92
|
+
next_chunk = chunk
|
93
|
+
else
|
94
|
+
# Oh no! Requested a chunk, but received the entire content
|
95
|
+
chunk_index = @offset - (download_offset - chunk.bytesize)
|
96
|
+
next_chunk = chunk.byteslice(chunk_index..-1)
|
97
|
+
next if next_chunk.nil?
|
98
|
+
end
|
99
99
|
|
100
|
-
|
101
|
-
|
100
|
+
# logger.debug { sprintf('Writing chunk (%d bytes, %d total)', chunk.length, bytes_read) }
|
101
|
+
@download_io.write(next_chunk)
|
102
102
|
|
103
|
-
|
103
|
+
@offset += next_chunk.bytesize
|
104
|
+
end
|
104
105
|
end
|
105
106
|
|
106
|
-
|
107
|
+
@download_io.flush if @download_io.respond_to?(:flush)
|
107
108
|
|
108
109
|
if @close_io_on_finish
|
109
110
|
result = nil
|
110
111
|
else
|
111
112
|
result = @download_io
|
112
113
|
end
|
113
|
-
check_status(http_res.status.to_i, http_res.
|
114
|
+
check_status(http_res.status.to_i, http_res.headers, http_res.body)
|
114
115
|
success(result, &block)
|
115
116
|
rescue => e
|
116
117
|
@download_io.flush if @download_io.respond_to?(:flush)
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# Copyright 2025 Google LLC
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require "faraday"
|
16
|
+
require "faraday/follow_redirects"
|
17
|
+
|
18
|
+
module Google
|
19
|
+
module Apis
|
20
|
+
module Core
|
21
|
+
# Customized version of the FollowRedirects middleware that does not
|
22
|
+
# trigger on 308. HttpCommand wants to handle 308 itself for resumable
|
23
|
+
# uploads.
|
24
|
+
class FollowRedirectsMiddleware < Faraday::FollowRedirects::Middleware
|
25
|
+
def follow_redirect?(env, response)
|
26
|
+
super && response.status != 308
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
Faraday::Response.register_middleware(follow_redirects_google_apis_core: FollowRedirectsMiddleware)
|
31
|
+
|
32
|
+
# Customized subclass of Faraday::Response with additional capabilities
|
33
|
+
# needed by older versions of some downstream dependencies.
|
34
|
+
class Response < Faraday::Response
|
35
|
+
# Compatibility alias.
|
36
|
+
# Earlier versions based on the old `httpclient` gem used `HTTP::Message`,
|
37
|
+
# which defined the `header` field that some clients, notably
|
38
|
+
# google-cloud-storage, depend on.
|
39
|
+
# Faraday's `headers` isn't an exact replacement because its values are
|
40
|
+
# single strings whereas `HTTP::Message` values are arrays, but
|
41
|
+
# google-cloud-storage already passes the result through `Array()` so this
|
42
|
+
# should work sufficiently.
|
43
|
+
alias header headers
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -17,6 +17,7 @@ require 'addressable/template'
|
|
17
17
|
require 'google/apis/options'
|
18
18
|
require 'google/apis/errors'
|
19
19
|
require 'retriable'
|
20
|
+
require 'google/apis/core/faraday_integration'
|
20
21
|
require 'google/apis/core/logging'
|
21
22
|
require 'pp'
|
22
23
|
|
@@ -59,8 +60,8 @@ module Google
|
|
59
60
|
# @return [symbol]
|
60
61
|
attr_accessor :method
|
61
62
|
|
62
|
-
#
|
63
|
-
# @return [
|
63
|
+
# Faraday connection
|
64
|
+
# @return [Faraday::Connection]
|
64
65
|
attr_accessor :connection
|
65
66
|
|
66
67
|
# Query params
|
@@ -96,8 +97,8 @@ module Google
|
|
96
97
|
|
97
98
|
# Execute the command, retrying as necessary
|
98
99
|
#
|
99
|
-
# @param [
|
100
|
-
#
|
100
|
+
# @param [Faraday::Connection] client
|
101
|
+
# Faraday connection
|
101
102
|
# @yield [result, err] Result or error if block supplied
|
102
103
|
# @return [Object]
|
103
104
|
# @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
|
@@ -181,7 +182,7 @@ module Google
|
|
181
182
|
@form_encoded = false
|
182
183
|
end
|
183
184
|
|
184
|
-
self.body = ''
|
185
|
+
self.body = '' if self.body.nil? && [:post, :put, :patch].include?(method)
|
185
186
|
end
|
186
187
|
|
187
188
|
# Release any resources used by this command
|
@@ -205,7 +206,7 @@ module Google
|
|
205
206
|
# @raise [Google::Apis::AuthorizationError] Authorization is required
|
206
207
|
def process_response(status, header, body)
|
207
208
|
check_status(status, header, body)
|
208
|
-
decode_response_body(header['Content-Type'].first, body)
|
209
|
+
decode_response_body(Array(header['Content-Type']).first, body)
|
209
210
|
end
|
210
211
|
|
211
212
|
# Check the response and raise error if needed
|
@@ -284,17 +285,10 @@ module Google
|
|
284
285
|
# @raise [StandardError] if no block
|
285
286
|
def error(err, rethrow: false, &block)
|
286
287
|
logger.debug { sprintf('Error - %s', PP.pp(err, +'')) }
|
287
|
-
if err.is_a?(
|
288
|
-
|
289
|
-
|
290
|
-
raise Google::Apis::TransmissionError.new(err) if res.nil?
|
291
|
-
check_status(res.status.to_i, res.header, res.body)
|
292
|
-
rescue Google::Apis::Error => e
|
293
|
-
err = e
|
294
|
-
end
|
295
|
-
elsif err.is_a?(HTTPClient::TimeoutError) ||
|
288
|
+
if err.is_a?(Faraday::FollowRedirects::RedirectLimitReached)
|
289
|
+
err = Google::Apis::RedirectError.new(err)
|
290
|
+
elsif err.is_a?(Faraday::Error) ||
|
296
291
|
err.is_a?(SocketError) ||
|
297
|
-
err.is_a?(HTTPClient::KeepAliveDisconnected) ||
|
298
292
|
err.is_a?(Errno::ECONNREFUSED) ||
|
299
293
|
err.is_a?(Errno::ETIMEDOUT) ||
|
300
294
|
err.is_a?(Errno::ECONNRESET)
|
@@ -307,8 +301,8 @@ module Google
|
|
307
301
|
# Execute the command once.
|
308
302
|
#
|
309
303
|
# @private
|
310
|
-
# @param [
|
311
|
-
#
|
304
|
+
# @param [Faraday::Connection] client
|
305
|
+
# Faraday connection
|
312
306
|
# @return [Object]
|
313
307
|
# @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
|
314
308
|
# @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
|
@@ -320,15 +314,11 @@ module Google
|
|
320
314
|
request_header = header.dup
|
321
315
|
apply_request_options(request_header)
|
322
316
|
|
323
|
-
@http_res = client.
|
324
|
-
|
325
|
-
query: nil,
|
326
|
-
body: body,
|
327
|
-
header: request_header,
|
328
|
-
follow_redirect: true)
|
317
|
+
@http_res = client.run_request(method, url.to_s, body, request_header)
|
318
|
+
|
329
319
|
logger.debug { @http_res.status }
|
330
320
|
logger.debug { safe_single_line_representation @http_res }
|
331
|
-
response = process_response(@http_res.status.to_i, @http_res.
|
321
|
+
response = process_response(@http_res.status.to_i, @http_res.headers, @http_res.body)
|
332
322
|
success(response)
|
333
323
|
rescue => e
|
334
324
|
logger.debug { sprintf('Caught error %s', e) }
|
@@ -410,9 +400,14 @@ module Google
|
|
410
400
|
@opencensus_span.put_attribute "http.host", url.host.to_s
|
411
401
|
@opencensus_span.put_attribute "http.method", method.to_s.upcase
|
412
402
|
@opencensus_span.put_attribute "http.path", url.path.to_s
|
413
|
-
|
414
|
-
|
415
|
-
|
403
|
+
sent_size =
|
404
|
+
if body.respond_to? :bytesize
|
405
|
+
body.bytesize
|
406
|
+
elsif body.nil?
|
407
|
+
0
|
408
|
+
end
|
409
|
+
if sent_size
|
410
|
+
@opencensus_span.put_message_event OpenCensus::Trace::SpanBuilder::SENT, 1, sent_size
|
416
411
|
end
|
417
412
|
|
418
413
|
formatter = OpenCensus::Trace.config.http_formatter
|
@@ -30,8 +30,7 @@ module Google
|
|
30
30
|
# here too.
|
31
31
|
#
|
32
32
|
# @private
|
33
|
-
# @param [
|
34
|
-
# HTTP client
|
33
|
+
# @param [Faraday::Connection] client Faraday connection
|
35
34
|
# @yield [result, err] Result or error if block supplied
|
36
35
|
# @return [Object]
|
37
36
|
# @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
|
@@ -47,41 +46,45 @@ module Google
|
|
47
46
|
request_header[RANGE_HEADER] = sprintf('bytes=%d-', @offset)
|
48
47
|
end
|
49
48
|
|
50
|
-
http_res = client.get(url.to_s,
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
status = res.http_header.status_code.to_i
|
55
|
-
next unless OK_STATUS.include?(status)
|
49
|
+
http_res = client.get(url.to_s, query, request_header) do |request|
|
50
|
+
request.options.on_data = proc do |chunk, _size, res|
|
51
|
+
status = res.status.to_i
|
52
|
+
next if chunk.nil? || (status >= 300 && status < 400)
|
56
53
|
|
57
|
-
|
58
|
-
|
54
|
+
download_offset ||= (status == 206 ? @offset : 0)
|
55
|
+
download_offset += chunk.bytesize
|
59
56
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
57
|
+
if download_offset - chunk.bytesize == @offset
|
58
|
+
next_chunk = chunk
|
59
|
+
else
|
60
|
+
# Oh no! Requested a chunk, but received the entire content
|
61
|
+
chunk_index = @offset - (download_offset - chunk.bytesize)
|
62
|
+
next_chunk = chunk.byteslice(chunk_index..-1)
|
63
|
+
next if next_chunk.nil?
|
64
|
+
end
|
68
65
|
|
69
|
-
|
70
|
-
|
66
|
+
# logger.debug { sprintf('Writing chunk (%d bytes, %d total)', chunk.length, bytes_read) }
|
67
|
+
@download_io.write(next_chunk)
|
71
68
|
|
72
|
-
|
69
|
+
@offset += next_chunk.bytesize
|
70
|
+
end
|
73
71
|
end
|
74
72
|
|
75
|
-
|
73
|
+
@download_io.flush if @download_io.respond_to?(:flush)
|
76
74
|
|
77
75
|
if @close_io_on_finish
|
78
76
|
result = nil
|
79
77
|
else
|
80
78
|
result = @download_io
|
81
79
|
end
|
82
|
-
check_status(http_res.status.to_i, http_res.
|
83
|
-
# In case of file download in storage, we need to respond back with
|
84
|
-
#
|
80
|
+
check_status(http_res.status.to_i, http_res.headers, http_res.body)
|
81
|
+
# In case of file download in storage, we need to respond back with
|
82
|
+
# the http response object along with the result IO object, because
|
83
|
+
# google-cloud-storage uses the HTTP info.
|
84
|
+
# Also, older versions of google-cloud-storage assume this object
|
85
|
+
# conforms to the old httpclient response API instead of the Faraday
|
86
|
+
# response API. Return a subclass that provides the needed methods.
|
87
|
+
http_res = Core::Response.new http_res.env
|
85
88
|
success([result, http_res], &block)
|
86
89
|
rescue => e
|
87
90
|
@download_io.flush if @download_io.respond_to?(:flush)
|
@@ -94,8 +94,7 @@ module Google
|
|
94
94
|
|
95
95
|
# Execute the command, retrying as necessary
|
96
96
|
#
|
97
|
-
# @param [
|
98
|
-
# HTTP client
|
97
|
+
# @param [Faraday::Connection] client Faraday connection
|
99
98
|
# @yield [result, err] Result or error if block supplied
|
100
99
|
# @return [Object]
|
101
100
|
# @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
|
@@ -138,11 +137,10 @@ module Google
|
|
138
137
|
request_header[CONTENT_TYPE_HEADER] = JSON_CONTENT_TYPE
|
139
138
|
request_header[UPLOAD_CONTENT_TYPE_HEADER] = upload_content_type unless upload_content_type.nil?
|
140
139
|
|
141
|
-
response = client.post(url.to_s,
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
result = process_response(response.status_code, response.header, response.body)
|
140
|
+
response = client.post(url.to_s, body, request_header) do |request|
|
141
|
+
request.params.replace(request_query)
|
142
|
+
end
|
143
|
+
result = process_response(response.status.to_i, response.headers, response.body)
|
146
144
|
success(result)
|
147
145
|
rescue => e
|
148
146
|
error(e, rethrow: true)
|
@@ -166,8 +164,7 @@ module Google
|
|
166
164
|
|
167
165
|
# Send the actual content
|
168
166
|
#
|
169
|
-
# @param [
|
170
|
-
# HTTP client
|
167
|
+
# @param [Faraday::Connection] client Faraday connection
|
171
168
|
# @return [HTTP::Message]
|
172
169
|
# @raise [Google::Apis::ServerError] Unable to send the request
|
173
170
|
def send_upload_command(client)
|
@@ -178,7 +175,7 @@ module Google
|
|
178
175
|
|
179
176
|
request_header = header.dup
|
180
177
|
request_header[CONTENT_RANGE_HEADER] = get_content_range_header current_chunk_size
|
181
|
-
request_header[CONTENT_LENGTH_HEADER] = current_chunk_size
|
178
|
+
request_header[CONTENT_LENGTH_HEADER] = current_chunk_size.to_s
|
182
179
|
chunk_body =
|
183
180
|
if @upload_chunk_size == 0
|
184
181
|
upload_io
|
@@ -186,10 +183,10 @@ module Google
|
|
186
183
|
StringIO.new(upload_io.read(current_chunk_size))
|
187
184
|
end
|
188
185
|
|
189
|
-
response = client.put(@upload_url,
|
186
|
+
response = client.put(@upload_url, chunk_body, request_header)
|
190
187
|
|
191
|
-
result = process_response(response.
|
192
|
-
@upload_incomplete = false if response.
|
188
|
+
result = process_response(response.status.to_i, response.headers, response.body)
|
189
|
+
@upload_incomplete = false if response.status.to_i.eql? OK_STATUS
|
193
190
|
@offset += current_chunk_size if @upload_incomplete
|
194
191
|
success(result)
|
195
192
|
rescue => e
|
@@ -214,7 +211,8 @@ module Google
|
|
214
211
|
# @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
|
215
212
|
# @raise [Google::Apis::AuthorizationError] Authorization is required
|
216
213
|
def process_response(status, header, body)
|
217
|
-
|
214
|
+
location_header = Array(header[LOCATION_HEADER])
|
215
|
+
@upload_url = location_header.first unless location_header.empty?
|
218
216
|
super(status, header, body)
|
219
217
|
end
|
220
218
|
|
@@ -224,7 +222,7 @@ module Google
|
|
224
222
|
request_header[CONTENT_RANGE_HEADER] = "bytes */#{upload_io.size}"
|
225
223
|
request_header[CONTENT_LENGTH_HEADER] = '0'
|
226
224
|
# Initiating call
|
227
|
-
response = client.put(@upload_url,
|
225
|
+
response = client.put(@upload_url, "", request_header)
|
228
226
|
handle_resumable_upload_http_response_codes(response)
|
229
227
|
end
|
230
228
|
|
@@ -234,25 +232,25 @@ module Google
|
|
234
232
|
request_header = header.dup
|
235
233
|
request_header[CONTENT_LENGTH_HEADER] = '0'
|
236
234
|
# Initiating call
|
237
|
-
response = client.delete(@upload_url,
|
235
|
+
response = client.delete(@upload_url, nil, request_header)
|
238
236
|
handle_resumable_upload_http_response_codes(response)
|
239
237
|
|
240
|
-
if !@upload_incomplete && (400..499).include?(response.
|
238
|
+
if !@upload_incomplete && (400..499).include?(response.status.to_i)
|
241
239
|
@close_io_on_finish = true
|
242
240
|
true # method returns true if upload is successfully cancelled
|
243
241
|
else
|
244
|
-
logger.debug { sprintf("Failed to cancel upload session. Response: #{response.
|
242
|
+
logger.debug { sprintf("Failed to cancel upload session. Response: #{response.status.to_i} - #{response.body}") }
|
245
243
|
end
|
246
244
|
|
247
245
|
end
|
248
246
|
|
249
247
|
def handle_resumable_upload_http_response_codes(response)
|
250
|
-
code = response.
|
248
|
+
code = response.status.to_i
|
251
249
|
|
252
250
|
case code
|
253
251
|
when 308
|
254
252
|
if response.headers['Range']
|
255
|
-
range = response.headers['Range']
|
253
|
+
range = Array(response.headers['Range']).first
|
256
254
|
@offset = range.split('-').last.to_i + 1
|
257
255
|
logger.debug { sprintf("Upload is incomplete. Bytes uploaded so far: #{range}") }
|
258
256
|
else
|
@@ -266,7 +264,7 @@ module Google
|
|
266
264
|
# Upload is complete.
|
267
265
|
@upload_incomplete = false
|
268
266
|
else
|
269
|
-
logger.debug { sprintf("Unexpected response: #{response.
|
267
|
+
logger.debug { sprintf("Unexpected response: #{response.status.to_i} - #{response.body}") }
|
270
268
|
@upload_incomplete = true
|
271
269
|
end
|
272
270
|
end
|
@@ -30,6 +30,7 @@ module Google
|
|
30
30
|
UPLOAD_CONTENT_TYPE_HEADER = 'X-Goog-Upload-Header-Content-Type'
|
31
31
|
UPLOAD_CONTENT_LENGTH = 'X-Goog-Upload-Header-Content-Length'
|
32
32
|
CONTENT_TYPE_HEADER = 'Content-Type'
|
33
|
+
CONTENT_LENGTH_HEADER = "Content-Length"
|
33
34
|
|
34
35
|
# File name or IO containing the content to upload
|
35
36
|
# @return [String, File, #read]
|
@@ -159,9 +160,11 @@ module Google
|
|
159
160
|
# @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
|
160
161
|
# @raise [Google::Apis::AuthorizationError] Authorization is required
|
161
162
|
def process_response(status, header, body)
|
162
|
-
|
163
|
-
@
|
164
|
-
|
163
|
+
bytes_received_header = Array(header[BYTES_RECEIVED_HEADER])
|
164
|
+
@offset = Integer(bytes_received_header.first) unless bytes_received_header.empty?
|
165
|
+
upload_url_header = Array(header[UPLOAD_URL_HEADER])
|
166
|
+
@upload_url = upload_url_header.first unless upload_url_header.empty?
|
167
|
+
upload_status = Array(header[UPLOAD_STATUS_HEADER]).first
|
165
168
|
logger.debug { sprintf('Upload status %s', upload_status) }
|
166
169
|
if upload_status == STATUS_ACTIVE
|
167
170
|
@state = :active
|
@@ -184,19 +187,14 @@ module Google
|
|
184
187
|
request_header[UPLOAD_CONTENT_LENGTH] = upload_io.size.to_s
|
185
188
|
request_header[UPLOAD_CONTENT_TYPE_HEADER] = upload_content_type
|
186
189
|
|
187
|
-
client.
|
188
|
-
url.to_s, query: nil,
|
189
|
-
body: body,
|
190
|
-
header: request_header,
|
191
|
-
follow_redirect: true)
|
190
|
+
client.run_request(method, url.to_s, body, request_header)
|
192
191
|
rescue => e
|
193
192
|
raise Google::Apis::ServerError, e.message
|
194
193
|
end
|
195
194
|
|
196
195
|
# Query for the status of an incomplete upload
|
197
196
|
#
|
198
|
-
# @param [
|
199
|
-
# HTTP client
|
197
|
+
# @param [Faraday::Connection] client Faraday connection
|
200
198
|
# @return [HTTP::Message]
|
201
199
|
# @raise [Google::Apis::ServerError] Unable to send the request
|
202
200
|
def send_query_command(client)
|
@@ -206,14 +204,13 @@ module Google
|
|
206
204
|
apply_request_options(request_header)
|
207
205
|
request_header[UPLOAD_COMMAND_HEADER] = QUERY_COMMAND
|
208
206
|
|
209
|
-
client.post(@upload_url,
|
207
|
+
client.post(@upload_url, '', request_header)
|
210
208
|
end
|
211
209
|
|
212
210
|
|
213
211
|
# Send the actual content
|
214
212
|
#
|
215
|
-
# @param [
|
216
|
-
# HTTP client
|
213
|
+
# @param [Faraday::Connection] client Faraday connection
|
217
214
|
# @return [HTTP::Message]
|
218
215
|
# @raise [Google::Apis::ServerError] Unable to send the request
|
219
216
|
def send_upload_command(client)
|
@@ -228,16 +225,16 @@ module Google
|
|
228
225
|
request_header[UPLOAD_COMMAND_HEADER] = UPLOAD_COMMAND
|
229
226
|
request_header[UPLOAD_OFFSET_HEADER] = @offset.to_s
|
230
227
|
request_header[CONTENT_TYPE_HEADER] = upload_content_type
|
228
|
+
request_header[CONTENT_LENGTH_HEADER] = (upload_io.size - @offset).to_s
|
231
229
|
|
232
|
-
client.post(@upload_url,
|
230
|
+
client.post(@upload_url, content, request_header)
|
233
231
|
end
|
234
232
|
|
235
233
|
# Execute the upload request once. This will typically perform two HTTP requests -- one to initiate or query
|
236
234
|
# for the status of the upload, the second to send the (remaining) content.
|
237
235
|
#
|
238
236
|
# @private
|
239
|
-
# @param [
|
240
|
-
# HTTP client
|
237
|
+
# @param [Faraday::Connection] client Faraday connection
|
241
238
|
# @yield [result, err] Result or error if block supplied
|
242
239
|
# @return [Object]
|
243
240
|
# @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
|
@@ -247,16 +244,16 @@ module Google
|
|
247
244
|
case @state
|
248
245
|
when :start
|
249
246
|
response = send_start_command(client)
|
250
|
-
result = process_response(response.
|
247
|
+
result = process_response(response.status.to_i, response.headers, response.body)
|
251
248
|
when :active
|
252
249
|
response = send_query_command(client)
|
253
|
-
result = process_response(response.
|
250
|
+
result = process_response(response.status.to_i, response.headers, response.body)
|
254
251
|
when :cancelled, :final
|
255
252
|
error(@last_error, rethrow: true, &block)
|
256
253
|
end
|
257
254
|
if @state == :active
|
258
255
|
response = send_upload_command(client)
|
259
|
-
result = process_response(response.
|
256
|
+
result = process_response(response.status.to_i, response.headers, response.body)
|
260
257
|
end
|
261
258
|
|
262
259
|
success(result, &block) if @state == :final
|
data/lib/google/apis/options.rb
CHANGED
@@ -61,7 +61,7 @@ module Google
|
|
61
61
|
# @!attribute [rw] read_timeout_sec
|
62
62
|
# @return [Integer] How long, in seconds, before receiving data times out
|
63
63
|
# @!attribute [rw] transparent_gzip_decompression
|
64
|
-
#
|
64
|
+
# @return [Boolean] DEPRECATED. Gzip decompression is now always on.
|
65
65
|
# Get the default options
|
66
66
|
# @return [Google::Apis::ClientOptions]
|
67
67
|
def self.default
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: google-apis-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Google LLC
|
@@ -27,104 +27,92 @@ dependencies:
|
|
27
27
|
name: retriable
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
29
29
|
requirements:
|
30
|
-
- - "
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: '2.0'
|
33
|
-
- - "<"
|
30
|
+
- - "~>"
|
34
31
|
- !ruby/object:Gem::Version
|
35
|
-
version:
|
32
|
+
version: '3.1'
|
36
33
|
type: :runtime
|
37
34
|
prerelease: false
|
38
35
|
version_requirements: !ruby/object:Gem::Requirement
|
39
36
|
requirements:
|
40
|
-
- - "
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
version: '2.0'
|
43
|
-
- - "<"
|
37
|
+
- - "~>"
|
44
38
|
- !ruby/object:Gem::Version
|
45
|
-
version:
|
39
|
+
version: '3.1'
|
46
40
|
- !ruby/object:Gem::Dependency
|
47
41
|
name: addressable
|
48
42
|
requirement: !ruby/object:Gem::Requirement
|
49
43
|
requirements:
|
50
44
|
- - "~>"
|
51
45
|
- !ruby/object:Gem::Version
|
52
|
-
version: '2.
|
46
|
+
version: '2.8'
|
53
47
|
- - ">="
|
54
48
|
- !ruby/object:Gem::Version
|
55
|
-
version: 2.
|
49
|
+
version: 2.8.7
|
56
50
|
type: :runtime
|
57
51
|
prerelease: false
|
58
52
|
version_requirements: !ruby/object:Gem::Requirement
|
59
53
|
requirements:
|
60
54
|
- - "~>"
|
61
55
|
- !ruby/object:Gem::Version
|
62
|
-
version: '2.
|
56
|
+
version: '2.8'
|
63
57
|
- - ">="
|
64
58
|
- !ruby/object:Gem::Version
|
65
|
-
version: 2.
|
59
|
+
version: 2.8.7
|
66
60
|
- !ruby/object:Gem::Dependency
|
67
61
|
name: mini_mime
|
68
62
|
requirement: !ruby/object:Gem::Requirement
|
69
63
|
requirements:
|
70
64
|
- - "~>"
|
71
65
|
- !ruby/object:Gem::Version
|
72
|
-
version: '1.
|
66
|
+
version: '1.1'
|
73
67
|
type: :runtime
|
74
68
|
prerelease: false
|
75
69
|
version_requirements: !ruby/object:Gem::Requirement
|
76
70
|
requirements:
|
77
71
|
- - "~>"
|
78
72
|
- !ruby/object:Gem::Version
|
79
|
-
version: '1.
|
73
|
+
version: '1.1'
|
80
74
|
- !ruby/object:Gem::Dependency
|
81
75
|
name: googleauth
|
82
76
|
requirement: !ruby/object:Gem::Requirement
|
83
77
|
requirements:
|
84
78
|
- - "~>"
|
85
79
|
- !ruby/object:Gem::Version
|
86
|
-
version: '1.
|
80
|
+
version: '1.14'
|
87
81
|
type: :runtime
|
88
82
|
prerelease: false
|
89
83
|
version_requirements: !ruby/object:Gem::Requirement
|
90
84
|
requirements:
|
91
85
|
- - "~>"
|
92
86
|
- !ruby/object:Gem::Version
|
93
|
-
version: '1.
|
87
|
+
version: '1.14'
|
94
88
|
- !ruby/object:Gem::Dependency
|
95
|
-
name:
|
89
|
+
name: faraday
|
96
90
|
requirement: !ruby/object:Gem::Requirement
|
97
91
|
requirements:
|
98
|
-
- - "
|
99
|
-
- !ruby/object:Gem::Version
|
100
|
-
version: 2.8.3
|
101
|
-
- - "<"
|
92
|
+
- - "~>"
|
102
93
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
94
|
+
version: '2.13'
|
104
95
|
type: :runtime
|
105
96
|
prerelease: false
|
106
97
|
version_requirements: !ruby/object:Gem::Requirement
|
107
98
|
requirements:
|
108
|
-
- - "
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: 2.8.3
|
111
|
-
- - "<"
|
99
|
+
- - "~>"
|
112
100
|
- !ruby/object:Gem::Version
|
113
|
-
version:
|
101
|
+
version: '2.13'
|
114
102
|
- !ruby/object:Gem::Dependency
|
115
|
-
name:
|
103
|
+
name: faraday-follow_redirects
|
116
104
|
requirement: !ruby/object:Gem::Requirement
|
117
105
|
requirements:
|
118
|
-
- - "
|
106
|
+
- - "~>"
|
119
107
|
- !ruby/object:Gem::Version
|
120
|
-
version: '0'
|
108
|
+
version: '0.3'
|
121
109
|
type: :runtime
|
122
110
|
prerelease: false
|
123
111
|
version_requirements: !ruby/object:Gem::Requirement
|
124
112
|
requirements:
|
125
|
-
- - "
|
113
|
+
- - "~>"
|
126
114
|
- !ruby/object:Gem::Version
|
127
|
-
version: '0'
|
115
|
+
version: '0.3'
|
128
116
|
email: googleapis-packages@google.com
|
129
117
|
executables: []
|
130
118
|
extensions: []
|
@@ -147,6 +135,7 @@ files:
|
|
147
135
|
- lib/google/apis/core/batch.rb
|
148
136
|
- lib/google/apis/core/composite_io.rb
|
149
137
|
- lib/google/apis/core/download.rb
|
138
|
+
- lib/google/apis/core/faraday_integration.rb
|
150
139
|
- lib/google/apis/core/hashable.rb
|
151
140
|
- lib/google/apis/core/http_command.rb
|
152
141
|
- lib/google/apis/core/json_representation.rb
|
@@ -164,7 +153,7 @@ licenses:
|
|
164
153
|
metadata:
|
165
154
|
bug_tracker_uri: https://github.com/googleapis/google-api-ruby-client/issues
|
166
155
|
changelog_uri: https://github.com/googleapis/google-api-ruby-client/tree/main/google-apis-core/CHANGELOG.md
|
167
|
-
documentation_uri: https://googleapis.dev/ruby/google-apis-core/
|
156
|
+
documentation_uri: https://googleapis.dev/ruby/google-apis-core/v1.0.0
|
168
157
|
source_code_uri: https://github.com/googleapis/google-api-ruby-client/tree/main/google-apis-core
|
169
158
|
rdoc_options: []
|
170
159
|
require_paths:
|