google-apis-core 0.17.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 +12 -0
- data/OVERVIEW.md +18 -0
- data/lib/google/apis/core/base_service.rb +49 -36
- 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 +104 -17
- data/lib/google/apis/core/upload.rb +16 -19
- data/lib/google/apis/core/version.rb +1 -1
- data/lib/google/apis/options.rb +3 -2
- metadata +26 -37
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,17 @@
|
|
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
|
+
|
9
|
+
### 0.18.0 (2025-05-22)
|
10
|
+
|
11
|
+
#### Features
|
12
|
+
|
13
|
+
* Restart & delete resumable upload ([#21896](https://github.com/googleapis/google-api-ruby-client/issues/21896))
|
14
|
+
|
3
15
|
### 0.17.0 (2025-04-30)
|
4
16
|
|
5
17
|
#### 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
|
@@ -350,6 +350,36 @@ module Google
|
|
350
350
|
true
|
351
351
|
end
|
352
352
|
|
353
|
+
# Restarts An interrupted Resumable upload
|
354
|
+
# @param [String] bucket
|
355
|
+
# Name of the bucket where the upload is being performed.
|
356
|
+
# @param [IO, String] upload_source
|
357
|
+
# IO stream or filename containing content to upload
|
358
|
+
# @param [IO, String] upload_id
|
359
|
+
# unique id generated for an ongoing upload
|
360
|
+
|
361
|
+
def restart_resumable_upload(bucket, upload_source, upload_id, options: nil)
|
362
|
+
command = make_storage_upload_command(:put, 'b/{bucket}/o', options)
|
363
|
+
command.upload_source = upload_source
|
364
|
+
command.upload_id = upload_id
|
365
|
+
command.params['bucket'] = bucket unless bucket.nil?
|
366
|
+
execute_or_queue_command(command)
|
367
|
+
end
|
368
|
+
|
369
|
+
# Deletes An interrupted Resumable upload
|
370
|
+
# @param [String] bucket
|
371
|
+
# Name of the bucket where the upload is being performed.
|
372
|
+
# @param [IO, String] upload_id
|
373
|
+
# unique id generated for an ongoing upload
|
374
|
+
|
375
|
+
def delete_resumable_upload(bucket, upload_id, options: nil)
|
376
|
+
command = make_storage_upload_command(:delete, 'b/{bucket}/o', options)
|
377
|
+
command.upload_id = upload_id
|
378
|
+
command.params['bucket'] = bucket unless bucket.nil?
|
379
|
+
command.delete_upload = true
|
380
|
+
execute_or_queue_command(command)
|
381
|
+
end
|
382
|
+
|
353
383
|
protected
|
354
384
|
|
355
385
|
# Create a new upload command.
|
@@ -512,39 +542,22 @@ module Google
|
|
512
542
|
Thread.current[:google_api_batch_service] = nil
|
513
543
|
end
|
514
544
|
|
515
|
-
# Create a new HTTP
|
516
|
-
# @return [
|
545
|
+
# Create a new HTTP connection
|
546
|
+
# @return [Faraday::Connection]
|
517
547
|
def new_client
|
518
|
-
|
519
|
-
|
520
|
-
if client_options.
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
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
|
528
560
|
end
|
529
|
-
|
530
|
-
if client_options.read_timeout_sec
|
531
|
-
client.receive_timeout = client_options.read_timeout_sec
|
532
|
-
end
|
533
|
-
|
534
|
-
if client_options.send_timeout_sec
|
535
|
-
client.send_timeout = client_options.send_timeout_sec
|
536
|
-
end
|
537
|
-
|
538
|
-
client.follow_redirect_count = 5
|
539
|
-
client.default_header = { 'User-Agent' => user_agent }
|
540
|
-
|
541
|
-
client.debug_dev = logger if client_options.log_http_requests
|
542
|
-
|
543
|
-
# Make HttpClient use system default root CA path
|
544
|
-
# https://github.com/nahi/httpclient/issues/445
|
545
|
-
client.ssl_config.clear_cert_store
|
546
|
-
client.ssl_config.cert_store.set_default_paths
|
547
|
-
client
|
548
561
|
end
|
549
562
|
|
550
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)
|
@@ -49,6 +49,14 @@ module Google
|
|
49
49
|
# @return [Integer]
|
50
50
|
attr_accessor :upload_chunk_size
|
51
51
|
|
52
|
+
# Unique upload_id of a resumable upload
|
53
|
+
# @return [String]
|
54
|
+
attr_accessor :upload_id
|
55
|
+
|
56
|
+
# Boolean Value to specify is a resumable upload is to be deleted or not
|
57
|
+
# @return [Boolean]
|
58
|
+
attr_accessor :delete_upload
|
59
|
+
|
52
60
|
# Ensure the content is readable and wrapped in an IO instance.
|
53
61
|
#
|
54
62
|
# @return [void]
|
@@ -61,7 +69,6 @@ module Google
|
|
61
69
|
# asserting that it already has a body. Form encoding is never used
|
62
70
|
# by upload requests.
|
63
71
|
self.body = '' unless self.body
|
64
|
-
|
65
72
|
super
|
66
73
|
if streamable?(upload_source)
|
67
74
|
self.upload_io = upload_source
|
@@ -73,6 +80,8 @@ module Google
|
|
73
80
|
self.upload_content_type = type&.content_type
|
74
81
|
end
|
75
82
|
@close_io_on_finish = true
|
83
|
+
elsif !upload_id.nil? && delete_upload
|
84
|
+
@close_io_on_finish = false
|
76
85
|
else
|
77
86
|
fail Google::Apis::ClientError, 'Invalid upload source'
|
78
87
|
end
|
@@ -80,13 +89,12 @@ module Google
|
|
80
89
|
|
81
90
|
# Close IO stream when command done. Only closes the stream if it was opened by the command.
|
82
91
|
def release!
|
83
|
-
upload_io.close if @close_io_on_finish
|
92
|
+
upload_io.close if @close_io_on_finish && !upload_io.nil?
|
84
93
|
end
|
85
94
|
|
86
95
|
# Execute the command, retrying as necessary
|
87
96
|
#
|
88
|
-
# @param [
|
89
|
-
# HTTP client
|
97
|
+
# @param [Faraday::Connection] client Faraday connection
|
90
98
|
# @yield [result, err] Result or error if block supplied
|
91
99
|
# @return [Object]
|
92
100
|
# @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
|
@@ -96,8 +104,16 @@ module Google
|
|
96
104
|
prepare!
|
97
105
|
opencensus_begin_span
|
98
106
|
@upload_chunk_size = options.upload_chunk_size
|
107
|
+
if upload_id.nil?
|
108
|
+
res = do_retry :initiate_resumable_upload, client
|
109
|
+
elsif delete_upload && !upload_id.nil?
|
110
|
+
construct_resumable_upload_url upload_id
|
111
|
+
res = do_retry :cancel_resumable_upload, client
|
112
|
+
else
|
113
|
+
construct_resumable_upload_url upload_id
|
114
|
+
res = do_retry :reinitiate_resumable_upload, client
|
115
|
+
end
|
99
116
|
|
100
|
-
do_retry :initiate_resumable_upload, client
|
101
117
|
while @upload_incomplete
|
102
118
|
res = do_retry :send_upload_command, client
|
103
119
|
end
|
@@ -121,20 +137,34 @@ module Google
|
|
121
137
|
request_header[CONTENT_TYPE_HEADER] = JSON_CONTENT_TYPE
|
122
138
|
request_header[UPLOAD_CONTENT_TYPE_HEADER] = upload_content_type unless upload_content_type.nil?
|
123
139
|
|
124
|
-
response = client.post(url.to_s,
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
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)
|
129
144
|
success(result)
|
130
145
|
rescue => e
|
131
146
|
error(e, rethrow: true)
|
132
147
|
end
|
133
148
|
|
149
|
+
# Reinitiating resumable upload
|
150
|
+
def reinitiate_resumable_upload(client)
|
151
|
+
logger.debug { sprintf('Restarting resumable upload command to %s', url) }
|
152
|
+
check_resumable_upload client
|
153
|
+
upload_io.pos = @offset
|
154
|
+
end
|
155
|
+
|
156
|
+
# Making resumable upload url from upload_id
|
157
|
+
def construct_resumable_upload_url(upload_id)
|
158
|
+
query_params = query.dup
|
159
|
+
query_params['uploadType'] = RESUMABLE
|
160
|
+
query_params['upload_id'] = upload_id
|
161
|
+
resumable_upload_params = query_params.map { |key, value| "#{key}=#{value}" }.join('&')
|
162
|
+
@upload_url = "#{url}&#{resumable_upload_params}"
|
163
|
+
end
|
164
|
+
|
134
165
|
# Send the actual content
|
135
166
|
#
|
136
|
-
# @param [
|
137
|
-
# HTTP client
|
167
|
+
# @param [Faraday::Connection] client Faraday connection
|
138
168
|
# @return [HTTP::Message]
|
139
169
|
# @raise [Google::Apis::ServerError] Unable to send the request
|
140
170
|
def send_upload_command(client)
|
@@ -145,7 +175,7 @@ module Google
|
|
145
175
|
|
146
176
|
request_header = header.dup
|
147
177
|
request_header[CONTENT_RANGE_HEADER] = get_content_range_header current_chunk_size
|
148
|
-
request_header[CONTENT_LENGTH_HEADER] = current_chunk_size
|
178
|
+
request_header[CONTENT_LENGTH_HEADER] = current_chunk_size.to_s
|
149
179
|
chunk_body =
|
150
180
|
if @upload_chunk_size == 0
|
151
181
|
upload_io
|
@@ -153,13 +183,16 @@ module Google
|
|
153
183
|
StringIO.new(upload_io.read(current_chunk_size))
|
154
184
|
end
|
155
185
|
|
156
|
-
response = client.put(@upload_url,
|
186
|
+
response = client.put(@upload_url, chunk_body, request_header)
|
157
187
|
|
158
|
-
result = process_response(response.
|
159
|
-
@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
|
160
190
|
@offset += current_chunk_size if @upload_incomplete
|
161
191
|
success(result)
|
162
192
|
rescue => e
|
193
|
+
logger.warn {
|
194
|
+
"error occured please use uploadId-#{response.headers['X-GUploader-UploadID']} to resume your upload"
|
195
|
+
} unless response.nil?
|
163
196
|
upload_io.pos = @offset
|
164
197
|
error(e, rethrow: true)
|
165
198
|
end
|
@@ -178,10 +211,64 @@ module Google
|
|
178
211
|
# @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
|
179
212
|
# @raise [Google::Apis::AuthorizationError] Authorization is required
|
180
213
|
def process_response(status, header, body)
|
181
|
-
|
214
|
+
location_header = Array(header[LOCATION_HEADER])
|
215
|
+
@upload_url = location_header.first unless location_header.empty?
|
182
216
|
super(status, header, body)
|
183
217
|
end
|
184
218
|
|
219
|
+
def check_resumable_upload(client)
|
220
|
+
# Setting up request header
|
221
|
+
request_header = header.dup
|
222
|
+
request_header[CONTENT_RANGE_HEADER] = "bytes */#{upload_io.size}"
|
223
|
+
request_header[CONTENT_LENGTH_HEADER] = '0'
|
224
|
+
# Initiating call
|
225
|
+
response = client.put(@upload_url, "", request_header)
|
226
|
+
handle_resumable_upload_http_response_codes(response)
|
227
|
+
end
|
228
|
+
|
229
|
+
# Cancel resumable upload
|
230
|
+
def cancel_resumable_upload(client)
|
231
|
+
# Setting up request header
|
232
|
+
request_header = header.dup
|
233
|
+
request_header[CONTENT_LENGTH_HEADER] = '0'
|
234
|
+
# Initiating call
|
235
|
+
response = client.delete(@upload_url, nil, request_header)
|
236
|
+
handle_resumable_upload_http_response_codes(response)
|
237
|
+
|
238
|
+
if !@upload_incomplete && (400..499).include?(response.status.to_i)
|
239
|
+
@close_io_on_finish = true
|
240
|
+
true # method returns true if upload is successfully cancelled
|
241
|
+
else
|
242
|
+
logger.debug { sprintf("Failed to cancel upload session. Response: #{response.status.to_i} - #{response.body}") }
|
243
|
+
end
|
244
|
+
|
245
|
+
end
|
246
|
+
|
247
|
+
def handle_resumable_upload_http_response_codes(response)
|
248
|
+
code = response.status.to_i
|
249
|
+
|
250
|
+
case code
|
251
|
+
when 308
|
252
|
+
if response.headers['Range']
|
253
|
+
range = Array(response.headers['Range']).first
|
254
|
+
@offset = range.split('-').last.to_i + 1
|
255
|
+
logger.debug { sprintf("Upload is incomplete. Bytes uploaded so far: #{range}") }
|
256
|
+
else
|
257
|
+
logger.debug { sprintf('No bytes uploaded yet.') }
|
258
|
+
end
|
259
|
+
@upload_incomplete = true
|
260
|
+
when 400..499
|
261
|
+
# Upload is canceled
|
262
|
+
@upload_incomplete = false
|
263
|
+
when 200, 201
|
264
|
+
# Upload is complete.
|
265
|
+
@upload_incomplete = false
|
266
|
+
else
|
267
|
+
logger.debug { sprintf("Unexpected response: #{response.status.to_i} - #{response.body}") }
|
268
|
+
@upload_incomplete = true
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
185
272
|
def streamable?(upload_source)
|
186
273
|
upload_source.is_a?(IO) || upload_source.is_a?(StringIO) || upload_source.is_a?(Tempfile)
|
187
274
|
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
@@ -41,7 +41,8 @@ module Google
|
|
41
41
|
:quota_project,
|
42
42
|
:query,
|
43
43
|
:add_invocation_id_header,
|
44
|
-
:upload_chunk_size
|
44
|
+
:upload_chunk_size
|
45
|
+
)
|
45
46
|
|
46
47
|
# General client options
|
47
48
|
class ClientOptions
|
@@ -60,7 +61,7 @@ module Google
|
|
60
61
|
# @!attribute [rw] read_timeout_sec
|
61
62
|
# @return [Integer] How long, in seconds, before receiving data times out
|
62
63
|
# @!attribute [rw] transparent_gzip_decompression
|
63
|
-
#
|
64
|
+
# @return [Boolean] DEPRECATED. Gzip decompression is now always on.
|
64
65
|
# Get the default options
|
65
66
|
# @return [Google::Apis::ClientOptions]
|
66
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:
|
@@ -180,7 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
180
169
|
- !ruby/object:Gem::Version
|
181
170
|
version: '0'
|
182
171
|
requirements: []
|
183
|
-
rubygems_version: 3.6.
|
172
|
+
rubygems_version: 3.6.9
|
184
173
|
specification_version: 4
|
185
174
|
summary: Common utility and base classes for legacy Google REST clients
|
186
175
|
test_files: []
|