google-apis-core 0.15.0 → 1.0.2
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 +46 -0
- data/OVERVIEW.md +18 -0
- data/lib/google/apis/core/base_service.rb +50 -37
- data/lib/google/apis/core/batch.rb +7 -7
- data/lib/google/apis/core/composite_io.rb +1 -1
- data/lib/google/apis/core/download.rb +28 -24
- data/lib/google/apis/core/faraday_integration.rb +47 -0
- data/lib/google/apis/core/http_command.rb +33 -30
- data/lib/google/apis/core/multipart.rb +4 -4
- data/lib/google/apis/core/storage_download.rb +31 -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/errors.rb +1 -1
- data/lib/google/apis/options.rb +3 -2
- metadata +28 -43
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5d024f53c9ef6e0174ec201b40ed2d437fc17fa8e98ef9d154e9cc9bf62540a1
|
|
4
|
+
data.tar.gz: aa5a7b80813d3f3ad8bb89c732aec0ef6defa631f1f3c3710c94366d1f584346
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6dcac5014397a36e277fba550c9eef19320d2a28de16e209122a8ae2457227dedf970ed59a3dd04928e33e1b7184cd4daad15c1b8db6012f80bac957d26491b7
|
|
7
|
+
data.tar.gz: aa15768fe116318ab8c06228fb1962da38cc870ff3c9cd2911a4cb30ff1863bba9c0674a170e6c97f7fad9a8ac380d8180435908fd2865ed7fbff0a9b0e68a16
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,51 @@
|
|
|
1
1
|
# Release History
|
|
2
2
|
|
|
3
|
+
### 1.0.2 (2025-09-09)
|
|
4
|
+
|
|
5
|
+
#### Bug Fixes
|
|
6
|
+
|
|
7
|
+
* Handle nil response in on_data callback for Faraday streaming ([#24235](https://github.com/googleapis/google-api-ruby-client/issues/24235))
|
|
8
|
+
|
|
9
|
+
### 1.0.1 (2025-08-08)
|
|
10
|
+
|
|
11
|
+
#### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* Compute and send content-length header when posting a CompositeIO ([#23864](https://github.com/googleapis/google-api-ruby-client/issues/23864))
|
|
14
|
+
|
|
15
|
+
### 1.0.0 (2025-08-03)
|
|
16
|
+
|
|
17
|
+
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.
|
|
18
|
+
|
|
19
|
+
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.
|
|
20
|
+
|
|
21
|
+
### 0.18.0 (2025-05-22)
|
|
22
|
+
|
|
23
|
+
#### Features
|
|
24
|
+
|
|
25
|
+
* Restart & delete resumable upload ([#21896](https://github.com/googleapis/google-api-ruby-client/issues/21896))
|
|
26
|
+
|
|
27
|
+
### 0.17.0 (2025-04-30)
|
|
28
|
+
|
|
29
|
+
#### Features
|
|
30
|
+
|
|
31
|
+
* ruby 3.1 minimum, 3.4 default ([#22594](https://github.com/googleapis/google-api-ruby-client/issues/22594))
|
|
32
|
+
#### Bug Fixes
|
|
33
|
+
|
|
34
|
+
* Fixed a method redefined warning ([#21572](https://github.com/googleapis/google-api-ruby-client/issues/21572))
|
|
35
|
+
* Ensure compatibility with frozen string literals ([#21648](https://github.com/googleapis/google-api-ruby-client/issues/21648))
|
|
36
|
+
|
|
37
|
+
### 0.16.0 (2025-01-12)
|
|
38
|
+
|
|
39
|
+
#### Features
|
|
40
|
+
|
|
41
|
+
* add ECONNRESET error as retriable error ([#20354](https://github.com/googleapis/google-api-ruby-client/issues/20354))
|
|
42
|
+
|
|
43
|
+
### 0.15.1 (2024-07-29)
|
|
44
|
+
|
|
45
|
+
#### Bug Fixes
|
|
46
|
+
|
|
47
|
+
* remove rexml from dependencies ([#19971](https://github.com/googleapis/google-api-ruby-client/issues/19971))
|
|
48
|
+
|
|
3
49
|
### 0.15.0 (2024-05-13)
|
|
4
50
|
|
|
5
51
|
#### 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,9 +149,9 @@ module Google
|
|
|
149
149
|
# @return [Addressable::URI]
|
|
150
150
|
attr_accessor :batch_path
|
|
151
151
|
|
|
152
|
-
# HTTP
|
|
153
|
-
# @return [
|
|
154
|
-
|
|
152
|
+
# Faraday HTTP connection
|
|
153
|
+
# @return [Faraday::Connection]
|
|
154
|
+
attr_writer :client
|
|
155
155
|
|
|
156
156
|
# General settings
|
|
157
157
|
# @return [Google::Apis::ClientOptions]
|
|
@@ -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
|
|
@@ -46,7 +48,7 @@ module Google
|
|
|
46
48
|
@download_io = File.open(download_dest, 'wb')
|
|
47
49
|
@close_io_on_finish = true
|
|
48
50
|
else
|
|
49
|
-
@download_io = StringIO.new('', 'wb')
|
|
51
|
+
@download_io = StringIO.new(+'', 'wb')
|
|
50
52
|
@close_io_on_finish = false
|
|
51
53
|
end
|
|
52
54
|
super
|
|
@@ -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,42 @@ 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
|
-
|
|
86
|
-
|
|
82
|
+
http_res = client.get(url.to_s, query, request_header) do |request|
|
|
83
|
+
request.options.on_data = proc do |chunk, _size, res|
|
|
84
|
+
# The on_data callback is only invoked on a successful response.
|
|
85
|
+
# Some Faraday adapters (e.g. Typhoeus) may not provide a response
|
|
86
|
+
# object in the callback, so we default to a 200 OK status.
|
|
87
|
+
status = res ? res.status.to_i : 200
|
|
88
|
+
next if chunk.nil? || (status >= 300 && status < 400)
|
|
87
89
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
# HTTP 206 is Partial Content
|
|
91
|
+
download_offset ||= (status == 206 ? @offset : 0)
|
|
92
|
+
download_offset += chunk.bytesize
|
|
90
93
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
94
|
+
if download_offset - chunk.bytesize == @offset
|
|
95
|
+
next_chunk = chunk
|
|
96
|
+
else
|
|
97
|
+
# Oh no! Requested a chunk, but received the entire content
|
|
98
|
+
chunk_index = @offset - (download_offset - chunk.bytesize)
|
|
99
|
+
next_chunk = chunk.byteslice(chunk_index..-1)
|
|
100
|
+
next if next_chunk.nil?
|
|
101
|
+
end
|
|
99
102
|
|
|
100
|
-
|
|
101
|
-
|
|
103
|
+
# logger.debug { sprintf('Writing chunk (%d bytes, %d total)', chunk.length, bytes_read) }
|
|
104
|
+
@download_io.write(next_chunk)
|
|
102
105
|
|
|
103
|
-
|
|
106
|
+
@offset += next_chunk.bytesize
|
|
107
|
+
end
|
|
104
108
|
end
|
|
105
109
|
|
|
106
|
-
|
|
110
|
+
@download_io.flush if @download_io.respond_to?(:flush)
|
|
107
111
|
|
|
108
112
|
if @close_io_on_finish
|
|
109
113
|
result = nil
|
|
110
114
|
else
|
|
111
115
|
result = @download_io
|
|
112
116
|
end
|
|
113
|
-
check_status(http_res.status.to_i, http_res.
|
|
117
|
+
check_status(http_res.status.to_i, http_res.headers, http_res.body)
|
|
114
118
|
success(result, &block)
|
|
115
119
|
rescue => e
|
|
116
120
|
@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,10 @@ 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)
|
|
186
|
+
if defined?(::Google::Apis::Core::CompositeIO) && body.is_a?(::Google::Apis::Core::CompositeIO)
|
|
187
|
+
header["Content-Length"] ||= body.size.to_s
|
|
188
|
+
end
|
|
185
189
|
end
|
|
186
190
|
|
|
187
191
|
# Release any resources used by this command
|
|
@@ -205,7 +209,7 @@ module Google
|
|
|
205
209
|
# @raise [Google::Apis::AuthorizationError] Authorization is required
|
|
206
210
|
def process_response(status, header, body)
|
|
207
211
|
check_status(status, header, body)
|
|
208
|
-
decode_response_body(header['Content-Type'].first, body)
|
|
212
|
+
decode_response_body(Array(header['Content-Type']).first, body)
|
|
209
213
|
end
|
|
210
214
|
|
|
211
215
|
# Check the response and raise error if needed
|
|
@@ -283,16 +287,14 @@ module Google
|
|
|
283
287
|
# @yield [nil, err] if block given
|
|
284
288
|
# @raise [StandardError] if no block
|
|
285
289
|
def error(err, rethrow: false, &block)
|
|
286
|
-
logger.debug { sprintf('Error - %s', PP.pp(err, '')) }
|
|
287
|
-
if err.is_a?(
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
end
|
|
295
|
-
elsif err.is_a?(HTTPClient::TimeoutError) || err.is_a?(SocketError) || err.is_a?(HTTPClient::KeepAliveDisconnected) || err.is_a?(Errno::ECONNREFUSED) || err.is_a?(Errno::ETIMEDOUT)
|
|
290
|
+
logger.debug { sprintf('Error - %s', PP.pp(err, +'')) }
|
|
291
|
+
if err.is_a?(Faraday::FollowRedirects::RedirectLimitReached)
|
|
292
|
+
err = Google::Apis::RedirectError.new(err)
|
|
293
|
+
elsif err.is_a?(Faraday::Error) ||
|
|
294
|
+
err.is_a?(SocketError) ||
|
|
295
|
+
err.is_a?(Errno::ECONNREFUSED) ||
|
|
296
|
+
err.is_a?(Errno::ETIMEDOUT) ||
|
|
297
|
+
err.is_a?(Errno::ECONNRESET)
|
|
296
298
|
err = Google::Apis::TransmissionError.new(err)
|
|
297
299
|
end
|
|
298
300
|
block.call(nil, err) if block_given?
|
|
@@ -302,8 +304,8 @@ module Google
|
|
|
302
304
|
# Execute the command once.
|
|
303
305
|
#
|
|
304
306
|
# @private
|
|
305
|
-
# @param [
|
|
306
|
-
#
|
|
307
|
+
# @param [Faraday::Connection] client
|
|
308
|
+
# Faraday connection
|
|
307
309
|
# @return [Object]
|
|
308
310
|
# @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
|
|
309
311
|
# @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
|
|
@@ -315,15 +317,11 @@ module Google
|
|
|
315
317
|
request_header = header.dup
|
|
316
318
|
apply_request_options(request_header)
|
|
317
319
|
|
|
318
|
-
@http_res = client.
|
|
319
|
-
|
|
320
|
-
query: nil,
|
|
321
|
-
body: body,
|
|
322
|
-
header: request_header,
|
|
323
|
-
follow_redirect: true)
|
|
320
|
+
@http_res = client.run_request(method, url.to_s, body, request_header)
|
|
321
|
+
|
|
324
322
|
logger.debug { @http_res.status }
|
|
325
323
|
logger.debug { safe_single_line_representation @http_res }
|
|
326
|
-
response = process_response(@http_res.status.to_i, @http_res.
|
|
324
|
+
response = process_response(@http_res.status.to_i, @http_res.headers, @http_res.body)
|
|
327
325
|
success(response)
|
|
328
326
|
rescue => e
|
|
329
327
|
logger.debug { sprintf('Caught error %s', e) }
|
|
@@ -380,7 +378,7 @@ module Google
|
|
|
380
378
|
end
|
|
381
379
|
|
|
382
380
|
def safe_pretty_representation obj
|
|
383
|
-
out = ""
|
|
381
|
+
out = +""
|
|
384
382
|
printer = RedactingPP.new out, 79
|
|
385
383
|
printer.guard_inspect_key { printer.pp obj }
|
|
386
384
|
printer.flush
|
|
@@ -388,7 +386,7 @@ module Google
|
|
|
388
386
|
end
|
|
389
387
|
|
|
390
388
|
def safe_single_line_representation obj
|
|
391
|
-
out = ""
|
|
389
|
+
out = +""
|
|
392
390
|
printer = RedactingSingleLine.new out
|
|
393
391
|
printer.guard_inspect_key { printer.pp obj }
|
|
394
392
|
printer.flush
|
|
@@ -405,9 +403,14 @@ module Google
|
|
|
405
403
|
@opencensus_span.put_attribute "http.host", url.host.to_s
|
|
406
404
|
@opencensus_span.put_attribute "http.method", method.to_s.upcase
|
|
407
405
|
@opencensus_span.put_attribute "http.path", url.path.to_s
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
406
|
+
sent_size =
|
|
407
|
+
if body.respond_to? :bytesize
|
|
408
|
+
body.bytesize
|
|
409
|
+
elsif body.nil?
|
|
410
|
+
0
|
|
411
|
+
end
|
|
412
|
+
if sent_size
|
|
413
|
+
@opencensus_span.put_message_event OpenCensus::Trace::SpanBuilder::SENT, 1, sent_size
|
|
411
414
|
end
|
|
412
415
|
|
|
413
416
|
formatter = OpenCensus::Trace.config.http_formatter
|
|
@@ -31,7 +31,7 @@ module Google
|
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def to_io(boundary)
|
|
34
|
-
part = ''
|
|
34
|
+
part = +''
|
|
35
35
|
part << "--#{boundary}\r\n"
|
|
36
36
|
part << "Content-Type: application/json\r\n"
|
|
37
37
|
@header.each do |(k, v)|
|
|
@@ -59,7 +59,7 @@ module Google
|
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
def to_io(boundary)
|
|
62
|
-
head = ''
|
|
62
|
+
head = +''
|
|
63
63
|
head << "--#{boundary}\r\n"
|
|
64
64
|
@header.each do |(k, v)|
|
|
65
65
|
head << "#{k}: #{v}\r\n"
|
|
@@ -67,7 +67,7 @@ module Google
|
|
|
67
67
|
head << "Content-Length: #{@length}\r\n" unless @length.nil?
|
|
68
68
|
head << "Content-Transfer-Encoding: binary\r\n"
|
|
69
69
|
head << "\r\n"
|
|
70
|
-
Google::Apis::Core::CompositeIO.new(StringIO.new(head), @io, StringIO.new("\r\n"))
|
|
70
|
+
Google::Apis::Core::CompositeIO.new(StringIO.new(head), @io, StringIO.new(+"\r\n"))
|
|
71
71
|
end
|
|
72
72
|
end
|
|
73
73
|
|
|
@@ -126,7 +126,7 @@ module Google
|
|
|
126
126
|
# @return [IO]
|
|
127
127
|
# IO stream
|
|
128
128
|
def assemble
|
|
129
|
-
@parts << StringIO.new("--#{@boundary}--\r\n\r\n")
|
|
129
|
+
@parts << StringIO.new(+"--#{@boundary}--\r\n\r\n")
|
|
130
130
|
Google::Apis::Core::CompositeIO.new(*@parts)
|
|
131
131
|
end
|
|
132
132
|
end
|
|
@@ -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,48 @@ 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
|
-
|
|
55
|
-
|
|
49
|
+
http_res = client.get(url.to_s, query, request_header) do |request|
|
|
50
|
+
request.options.on_data = proc do |chunk, _size, res|
|
|
51
|
+
# The on_data callback is only invoked on a successful response.
|
|
52
|
+
# Some Faraday adapters (e.g. Typhoeus) may not provide a response
|
|
53
|
+
# object in the callback, so we default to a 200 OK status.
|
|
54
|
+
status = res ? res.status.to_i : 200
|
|
55
|
+
next if chunk.nil? || (status >= 300 && status < 400)
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
download_offset ||= (status == 206 ? @offset : 0)
|
|
58
|
+
download_offset += chunk.bytesize
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
60
|
+
if download_offset - chunk.bytesize == @offset
|
|
61
|
+
next_chunk = chunk
|
|
62
|
+
else
|
|
63
|
+
# Oh no! Requested a chunk, but received the entire content
|
|
64
|
+
chunk_index = @offset - (download_offset - chunk.bytesize)
|
|
65
|
+
next_chunk = chunk.byteslice(chunk_index..-1)
|
|
66
|
+
next if next_chunk.nil?
|
|
67
|
+
end
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
# logger.debug { sprintf('Writing chunk (%d bytes, %d total)', chunk.length, bytes_read) }
|
|
70
|
+
@download_io.write(next_chunk)
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
@offset += next_chunk.bytesize
|
|
73
|
+
end
|
|
73
74
|
end
|
|
74
75
|
|
|
75
|
-
|
|
76
|
+
@download_io.flush if @download_io.respond_to?(:flush)
|
|
76
77
|
|
|
77
78
|
if @close_io_on_finish
|
|
78
79
|
result = nil
|
|
79
80
|
else
|
|
80
81
|
result = @download_io
|
|
81
82
|
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
|
-
#
|
|
83
|
+
check_status(http_res.status.to_i, http_res.headers, http_res.body)
|
|
84
|
+
# In case of file download in storage, we need to respond back with
|
|
85
|
+
# the http response object along with the result IO object, because
|
|
86
|
+
# google-cloud-storage uses the HTTP info.
|
|
87
|
+
# Also, older versions of google-cloud-storage assume this object
|
|
88
|
+
# conforms to the old httpclient response API instead of the Faraday
|
|
89
|
+
# response API. Return a subclass that provides the needed methods.
|
|
90
|
+
http_res = Core::Response.new http_res.env
|
|
85
91
|
success([result, http_res], &block)
|
|
86
92
|
rescue => e
|
|
87
93
|
@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/errors.rb
CHANGED
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,14 +1,13 @@
|
|
|
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.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Google LLC
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: representable
|
|
@@ -28,105 +27,92 @@ dependencies:
|
|
|
28
27
|
name: retriable
|
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
|
30
29
|
requirements:
|
|
31
|
-
- - "
|
|
32
|
-
- !ruby/object:Gem::Version
|
|
33
|
-
version: '2.0'
|
|
34
|
-
- - "<"
|
|
30
|
+
- - "~>"
|
|
35
31
|
- !ruby/object:Gem::Version
|
|
36
|
-
version:
|
|
32
|
+
version: '3.1'
|
|
37
33
|
type: :runtime
|
|
38
34
|
prerelease: false
|
|
39
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
40
36
|
requirements:
|
|
41
|
-
- - "
|
|
42
|
-
- !ruby/object:Gem::Version
|
|
43
|
-
version: '2.0'
|
|
44
|
-
- - "<"
|
|
37
|
+
- - "~>"
|
|
45
38
|
- !ruby/object:Gem::Version
|
|
46
|
-
version:
|
|
39
|
+
version: '3.1'
|
|
47
40
|
- !ruby/object:Gem::Dependency
|
|
48
41
|
name: addressable
|
|
49
42
|
requirement: !ruby/object:Gem::Requirement
|
|
50
43
|
requirements:
|
|
51
44
|
- - "~>"
|
|
52
45
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: '2.
|
|
46
|
+
version: '2.8'
|
|
54
47
|
- - ">="
|
|
55
48
|
- !ruby/object:Gem::Version
|
|
56
|
-
version: 2.
|
|
49
|
+
version: 2.8.7
|
|
57
50
|
type: :runtime
|
|
58
51
|
prerelease: false
|
|
59
52
|
version_requirements: !ruby/object:Gem::Requirement
|
|
60
53
|
requirements:
|
|
61
54
|
- - "~>"
|
|
62
55
|
- !ruby/object:Gem::Version
|
|
63
|
-
version: '2.
|
|
56
|
+
version: '2.8'
|
|
64
57
|
- - ">="
|
|
65
58
|
- !ruby/object:Gem::Version
|
|
66
|
-
version: 2.
|
|
59
|
+
version: 2.8.7
|
|
67
60
|
- !ruby/object:Gem::Dependency
|
|
68
61
|
name: mini_mime
|
|
69
62
|
requirement: !ruby/object:Gem::Requirement
|
|
70
63
|
requirements:
|
|
71
64
|
- - "~>"
|
|
72
65
|
- !ruby/object:Gem::Version
|
|
73
|
-
version: '1.
|
|
66
|
+
version: '1.1'
|
|
74
67
|
type: :runtime
|
|
75
68
|
prerelease: false
|
|
76
69
|
version_requirements: !ruby/object:Gem::Requirement
|
|
77
70
|
requirements:
|
|
78
71
|
- - "~>"
|
|
79
72
|
- !ruby/object:Gem::Version
|
|
80
|
-
version: '1.
|
|
73
|
+
version: '1.1'
|
|
81
74
|
- !ruby/object:Gem::Dependency
|
|
82
75
|
name: googleauth
|
|
83
76
|
requirement: !ruby/object:Gem::Requirement
|
|
84
77
|
requirements:
|
|
85
78
|
- - "~>"
|
|
86
79
|
- !ruby/object:Gem::Version
|
|
87
|
-
version: '1.
|
|
80
|
+
version: '1.14'
|
|
88
81
|
type: :runtime
|
|
89
82
|
prerelease: false
|
|
90
83
|
version_requirements: !ruby/object:Gem::Requirement
|
|
91
84
|
requirements:
|
|
92
85
|
- - "~>"
|
|
93
86
|
- !ruby/object:Gem::Version
|
|
94
|
-
version: '1.
|
|
87
|
+
version: '1.14'
|
|
95
88
|
- !ruby/object:Gem::Dependency
|
|
96
|
-
name:
|
|
89
|
+
name: faraday
|
|
97
90
|
requirement: !ruby/object:Gem::Requirement
|
|
98
91
|
requirements:
|
|
99
|
-
- - "
|
|
100
|
-
- !ruby/object:Gem::Version
|
|
101
|
-
version: 2.8.1
|
|
102
|
-
- - "<"
|
|
92
|
+
- - "~>"
|
|
103
93
|
- !ruby/object:Gem::Version
|
|
104
|
-
version:
|
|
94
|
+
version: '2.13'
|
|
105
95
|
type: :runtime
|
|
106
96
|
prerelease: false
|
|
107
97
|
version_requirements: !ruby/object:Gem::Requirement
|
|
108
98
|
requirements:
|
|
109
|
-
- - "
|
|
110
|
-
- !ruby/object:Gem::Version
|
|
111
|
-
version: 2.8.1
|
|
112
|
-
- - "<"
|
|
99
|
+
- - "~>"
|
|
113
100
|
- !ruby/object:Gem::Version
|
|
114
|
-
version:
|
|
101
|
+
version: '2.13'
|
|
115
102
|
- !ruby/object:Gem::Dependency
|
|
116
|
-
name:
|
|
103
|
+
name: faraday-follow_redirects
|
|
117
104
|
requirement: !ruby/object:Gem::Requirement
|
|
118
105
|
requirements:
|
|
119
|
-
- - "
|
|
106
|
+
- - "~>"
|
|
120
107
|
- !ruby/object:Gem::Version
|
|
121
|
-
version: '0'
|
|
108
|
+
version: '0.3'
|
|
122
109
|
type: :runtime
|
|
123
110
|
prerelease: false
|
|
124
111
|
version_requirements: !ruby/object:Gem::Requirement
|
|
125
112
|
requirements:
|
|
126
|
-
- - "
|
|
113
|
+
- - "~>"
|
|
127
114
|
- !ruby/object:Gem::Version
|
|
128
|
-
version: '0'
|
|
129
|
-
description:
|
|
115
|
+
version: '0.3'
|
|
130
116
|
email: googleapis-packages@google.com
|
|
131
117
|
executables: []
|
|
132
118
|
extensions: []
|
|
@@ -149,6 +135,7 @@ files:
|
|
|
149
135
|
- lib/google/apis/core/batch.rb
|
|
150
136
|
- lib/google/apis/core/composite_io.rb
|
|
151
137
|
- lib/google/apis/core/download.rb
|
|
138
|
+
- lib/google/apis/core/faraday_integration.rb
|
|
152
139
|
- lib/google/apis/core/hashable.rb
|
|
153
140
|
- lib/google/apis/core/http_command.rb
|
|
154
141
|
- lib/google/apis/core/json_representation.rb
|
|
@@ -166,9 +153,8 @@ licenses:
|
|
|
166
153
|
metadata:
|
|
167
154
|
bug_tracker_uri: https://github.com/googleapis/google-api-ruby-client/issues
|
|
168
155
|
changelog_uri: https://github.com/googleapis/google-api-ruby-client/tree/main/google-apis-core/CHANGELOG.md
|
|
169
|
-
documentation_uri: https://googleapis.dev/ruby/google-apis-core/
|
|
156
|
+
documentation_uri: https://googleapis.dev/ruby/google-apis-core/v1.0.2
|
|
170
157
|
source_code_uri: https://github.com/googleapis/google-api-ruby-client/tree/main/google-apis-core
|
|
171
|
-
post_install_message:
|
|
172
158
|
rdoc_options: []
|
|
173
159
|
require_paths:
|
|
174
160
|
- lib
|
|
@@ -176,15 +162,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
176
162
|
requirements:
|
|
177
163
|
- - ">="
|
|
178
164
|
- !ruby/object:Gem::Version
|
|
179
|
-
version: '
|
|
165
|
+
version: '3.1'
|
|
180
166
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
181
167
|
requirements:
|
|
182
168
|
- - ">="
|
|
183
169
|
- !ruby/object:Gem::Version
|
|
184
170
|
version: '0'
|
|
185
171
|
requirements: []
|
|
186
|
-
rubygems_version: 3.
|
|
187
|
-
signing_key:
|
|
172
|
+
rubygems_version: 3.6.9
|
|
188
173
|
specification_version: 4
|
|
189
174
|
summary: Common utility and base classes for legacy Google REST clients
|
|
190
175
|
test_files: []
|