google-apis-core 0.7.2 → 0.9.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 38cee6b3beff5b42204b1b518e742b3fe8925bc58d7a64565dd6744300193bb1
4
- data.tar.gz: f2b1ebe5ff08156d56867e1eb51520a6328c6654847ded469df9b90efc438208
3
+ metadata.gz: 39e8c0ee69956045fad35dd99b60187bee9a559e66c31141784f69c938b828da
4
+ data.tar.gz: 2bc2f65430050943360436b018b2149f876bdb190d8d637e42d1ac5c908aee41
5
5
  SHA512:
6
- metadata.gz: a888eda52341a233166b95641dd0bea997fff51f7242e5be0a1df449ffd19c9afdca57fb2d6fbad33f44aa7710a53d6939dd88538b60415d94b1f61087d8a78d
7
- data.tar.gz: bed80fd1c5b86c02ffcec60c5ca1fbe8c1cd434c62e96935b32f447dee61cbb5f3359d6580f82f0269b79028a1817c39c3470ebc8658cb98c7e56c45eab272cd
6
+ metadata.gz: 26a81d876d54cd42e9e84a4c057297ccd77a1cfebe481de646504f8e30d08496b72141581532dfeae03d3dcb9ff955330b7e94c81bc9bb555130e501fc2879f2
7
+ data.tar.gz: 2c1242fd64e8e66e82b04aa2a4f4c0fb0979e7a0a53f8162836a90a58242f1d46d4b8660101a15c9e82b6b6e48819cdffe5053f90894a9cf1dd5040de2c21db0
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Release History
2
2
 
3
+ ### 0.9.0 (2022-09-18)
4
+
5
+ #### Features
6
+
7
+ * add support to have invocation-id header ([#11655](https://github.com/googleapis/google-api-ruby-client/issues/11655))
8
+
9
+ ### 0.8.0 (2022-09-16)
10
+
11
+ #### Features
12
+
13
+ * Add storage upload to move away from unified upload protocol ([#11508](https://github.com/googleapis/google-api-ruby-client/issues/11508))
14
+
3
15
  ### 0.7.2 (2022-09-15)
4
16
 
5
17
  #### Bug Fixes
@@ -18,6 +18,7 @@ require 'google/apis/core/http_command'
18
18
  require 'google/apis/errors'
19
19
  require 'json'
20
20
  require 'retriable'
21
+ require "securerandom"
21
22
 
22
23
  module Google
23
24
  module Apis
@@ -161,6 +162,7 @@ module Google
161
162
  xgac = "gl-ruby/#{RUBY_VERSION} gdcl/#{munged_client_version}"
162
163
  xgac = old_xgac.empty? ? xgac : "#{old_xgac} #{xgac}"
163
164
  header.delete_if { |k, v| k.downcase == 'x-goog-api-client' }
165
+ xgac.concat(" ",invocation_id_header) if options.add_invocation_id_header
164
166
  header['X-Goog-Api-Client'] = xgac
165
167
  end
166
168
 
@@ -172,6 +174,10 @@ module Google
172
174
  header['X-Goog-User-Project'] = quota_project_id if quota_project_id
173
175
  end
174
176
 
177
+ def invocation_id_header
178
+ "gccl-invocation-id/#{SecureRandom.uuid}"
179
+ end
180
+
175
181
  # Attempt to parse a JSON error message
176
182
  # @param [String] body
177
183
  # HTTP response body
@@ -19,6 +19,7 @@ require 'google/apis/core/version'
19
19
  require 'google/apis/core/api_command'
20
20
  require 'google/apis/core/batch'
21
21
  require 'google/apis/core/upload'
22
+ require 'google/apis/core/storage_upload'
22
23
  require 'google/apis/core/download'
23
24
  require 'google/apis/core/storage_download'
24
25
  require 'google/apis/options'
@@ -318,6 +319,26 @@ module Google
318
319
  command
319
320
  end
320
321
 
322
+ # Create a new storage upload command.
323
+ # This is specifically for storage because we are moving to a new upload protocol.
324
+ # Ref: https://cloud.google.com/storage/docs/performing-resumable-uploads
325
+ #
326
+ # @param [Symbol] method
327
+ # HTTP method for uploading. The initial request to initiate a resumable session
328
+ # is :post and the subsequent chunks uploaded to the session are :put
329
+ # @param [String] path
330
+ # Additional path to upload endpoint, appended to API base path
331
+ # @param [Hash, Google::Apis::RequestOptions] options
332
+ # Request-specific options
333
+ # @return [Google::Apis::Core::StorageUploadCommand]
334
+ def make_storage_upload_command(method, path, options)
335
+ template = Addressable::Template.new(root_url + upload_path + path)
336
+ command = StorageUploadCommand.new(method, template, client_version: client_version)
337
+ command.options = request_options.merge(options)
338
+ apply_command_defaults(command)
339
+ command
340
+ end
341
+
321
342
  # Create a new download command.
322
343
  #
323
344
  # @param [symbol] method
@@ -28,6 +28,7 @@
28
28
  require 'google/apis/core/multipart'
29
29
  require 'google/apis/core/http_command'
30
30
  require 'google/apis/core/upload'
31
+ require 'google/apis/core/storage_upload'
31
32
  require 'google/apis/core/download'
32
33
  require 'google/apis/core/composite_io'
33
34
  require 'addressable/uri'
@@ -120,7 +121,7 @@ module Google
120
121
  end
121
122
 
122
123
  def ensure_valid_command(command)
123
- if command.is_a?(Google::Apis::Core::BaseUploadCommand) || command.is_a?(Google::Apis::Core::DownloadCommand) || command.is_a?(Google::Apis::Core::StorageDownloadCommand)
124
+ if command.is_a?(Google::Apis::Core::BaseUploadCommand) || command.is_a?(Google::Apis::Core::DownloadCommand) || command.is_a?(Google::Apis::Core::StorageDownloadCommand) || command.is_a?(Google::Apis::Core::StorageUploadCommand)
124
125
  fail Google::Apis::ClientError, 'Can not include media requests in batch'
125
126
  end
126
127
  fail Google::Apis::ClientError, 'Invalid command object' unless command.is_a?(HttpCommand)
@@ -98,9 +98,17 @@ module Google
98
98
  # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
99
99
  # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
100
100
  # @raise [Google::Apis::AuthorizationError] Authorization is required
101
- def execute(client)
101
+ def execute(client, &block)
102
102
  prepare!
103
103
  opencensus_begin_span
104
+ do_retry :execute_once, client, &block
105
+ ensure
106
+ opencensus_end_span
107
+ @http_res = nil
108
+ release!
109
+ end
110
+
111
+ def do_retry func, client
104
112
  begin
105
113
  Retriable.retriable tries: options.retries + 1,
106
114
  max_elapsed_time: options.max_elapsed_time,
@@ -115,7 +123,7 @@ module Google
115
123
  Retriable.retriable tries: auth_tries,
116
124
  on: [Google::Apis::AuthorizationError, Signet::AuthorizationError, Signet::RemoteServerError, Signet::UnexpectedStatusError],
117
125
  on_retry: proc { |*| refresh_authorization } do
118
- execute_once(client).tap do |result|
126
+ send(func, client).tap do |result|
119
127
  if block_given?
120
128
  yield result, nil
121
129
  end
@@ -129,10 +137,6 @@ module Google
129
137
  raise e
130
138
  end
131
139
  end
132
- ensure
133
- opencensus_end_span
134
- @http_res = nil
135
- release!
136
140
  end
137
141
 
138
142
  # Refresh the authorization authorization after a 401 error
@@ -216,7 +220,7 @@ module Google
216
220
  def check_status(status, header = nil, body = nil, message = nil)
217
221
  # TODO: 304 Not Modified depends on context...
218
222
  case status
219
- when 200...300
223
+ when 200...300, 308
220
224
  nil
221
225
  when 301, 302, 303, 307
222
226
  message ||= sprintf('Redirect to %s', header['Location'])
@@ -0,0 +1,181 @@
1
+ # Copyright 2022 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 'google/apis/core/http_command'
16
+ require 'google/apis/core/api_command'
17
+ require 'google/apis/errors'
18
+ require 'tempfile'
19
+ require 'mini_mime'
20
+
21
+ module Google
22
+ module Apis
23
+ module Core
24
+ # Base upload command. Not intended to be used directly
25
+ # @private
26
+ class StorageUploadCommand < ApiCommand
27
+ CONTENT_LENGTH_HEADER = "Content-Length"
28
+ CONTENT_TYPE_HEADER = "Content-Type"
29
+ UPLOAD_CONTENT_TYPE_HEADER = "X-Upload-Content-Type"
30
+ LOCATION_HEADER = "Location"
31
+ CONTENT_RANGE_HEADER = "Content-Range"
32
+ RESUMABLE = "resumable"
33
+ OK_STATUS = 200
34
+ CHUNK_SIZE = 8 * 1024 * 1024 # 8 MB
35
+
36
+ # File name or IO containing the content to upload
37
+ # @return [String, File, #read]
38
+ attr_accessor :upload_source
39
+
40
+ # Content type of the upload material
41
+ # @return [String]
42
+ attr_accessor :upload_content_type
43
+
44
+ # Content, as UploadIO
45
+ # @return [Google::Apis::Core::UploadIO]
46
+ attr_accessor :upload_io
47
+
48
+ # Ensure the content is readable and wrapped in an IO instance.
49
+ #
50
+ # @return [void]
51
+ # @raise [Google::Apis::ClientError] if upload source is invalid
52
+ def prepare!
53
+ @upload_url = nil
54
+ @offset = 0
55
+ @upload_incomplete = true
56
+ # Prevent the command from populating the body with form encoding, by
57
+ # asserting that it already has a body. Form encoding is never used
58
+ # by upload requests.
59
+ self.body = '' unless self.body
60
+
61
+ super
62
+ if streamable?(upload_source)
63
+ self.upload_io = upload_source
64
+ @close_io_on_finish = false
65
+ elsif self.upload_source.is_a?(String)
66
+ self.upload_io = File.new(upload_source, 'r')
67
+ if self.upload_content_type.nil?
68
+ type = MiniMime.lookup_by_filename(upload_source)
69
+ self.upload_content_type = type&.content_type
70
+ end
71
+ @close_io_on_finish = true
72
+ else
73
+ fail Google::Apis::ClientError, 'Invalid upload source'
74
+ end
75
+ end
76
+
77
+ # Close IO stream when command done. Only closes the stream if it was opened by the command.
78
+ def release!
79
+ upload_io.close if @close_io_on_finish
80
+ end
81
+
82
+ # Execute the command, retrying as necessary
83
+ #
84
+ # @param [HTTPClient] client
85
+ # HTTP client
86
+ # @yield [result, err] Result or error if block supplied
87
+ # @return [Object]
88
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
89
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
90
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
91
+ def execute(client)
92
+ prepare!
93
+ opencensus_begin_span
94
+
95
+ do_retry :initiate_resumable_upload, client
96
+ while @upload_incomplete
97
+ res = do_retry :send_upload_command, client
98
+ end
99
+ res
100
+ ensure
101
+ opencensus_end_span
102
+ @http_res = nil
103
+ release!
104
+ end
105
+
106
+ def initiate_resumable_upload(client)
107
+ logger.debug { sprintf('Intiating resumable upload command to %s', url) }
108
+
109
+ request_header = header.dup
110
+ apply_request_options(request_header)
111
+
112
+ request_query = query.dup
113
+ request_query['uploadType'] = RESUMABLE
114
+
115
+ request_header[CONTENT_LENGTH_HEADER] = upload_io.size.to_s
116
+ request_header[CONTENT_TYPE_HEADER] = JSON_CONTENT_TYPE
117
+ request_header[UPLOAD_CONTENT_TYPE_HEADER] = upload_content_type unless upload_content_type.nil?
118
+
119
+ response = client.post(url.to_s, query: request_query,
120
+ body: body,
121
+ header: request_header,
122
+ follow_redirect: true)
123
+ result = process_response(response.status_code, response.header, response.body)
124
+ success(result)
125
+ rescue => e
126
+ error(e, rethrow: true)
127
+ end
128
+
129
+ # Send the actual content
130
+ #
131
+ # @param [HTTPClient] client
132
+ # HTTP client
133
+ # @return [HTTP::Message]
134
+ # @raise [Google::Apis::ServerError] Unable to send the request
135
+ def send_upload_command(client)
136
+ logger.debug { sprintf('Sending upload command to %s', @upload_url) }
137
+
138
+ remaining_content_size = upload_io.size - @offset
139
+ current_chunk_size = remaining_content_size < CHUNK_SIZE ? remaining_content_size : CHUNK_SIZE
140
+
141
+ request_header = header.dup
142
+ request_header[CONTENT_RANGE_HEADER] = sprintf('bytes %d-%d/%d', @offset, @offset+current_chunk_size-1, upload_io.size)
143
+ request_header[CONTENT_LENGTH_HEADER] = current_chunk_size
144
+ chunk_body = upload_io.read(current_chunk_size)
145
+
146
+ response = client.put(@upload_url, body: chunk_body, header: request_header, follow_redirect: true)
147
+
148
+ result = process_response(response.status_code, response.header, response.body)
149
+ @upload_incomplete = false if response.status_code.eql? OK_STATUS
150
+ @offset += current_chunk_size if @upload_incomplete
151
+ success(result)
152
+ rescue => e
153
+ upload_io.pos = @offset
154
+ error(e, rethrow: true)
155
+ end
156
+
157
+ # Check the to see if the upload is complete or needs to be resumed.
158
+ #
159
+ # @param [Integer] status
160
+ # HTTP status code of response
161
+ # @param [HTTP::Message::Headers] header
162
+ # Response headers
163
+ # @param [String, #read] body
164
+ # Response body
165
+ # @return [Object]
166
+ # Response object
167
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
168
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
169
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
170
+ def process_response(status, header, body)
171
+ @upload_url = header[LOCATION_HEADER].first unless header[LOCATION_HEADER].empty?
172
+ super(status, header, body)
173
+ end
174
+
175
+ def streamable?(upload_source)
176
+ upload_source.is_a?(IO) || upload_source.is_a?(StringIO) || upload_source.is_a?(Tempfile)
177
+ end
178
+ end
179
+ end
180
+ end
181
+ end
@@ -16,7 +16,7 @@ module Google
16
16
  module Apis
17
17
  module Core
18
18
  # Core version
19
- VERSION = "0.7.2".freeze
19
+ VERSION = "0.9.0".freeze
20
20
  end
21
21
  end
22
22
  end
@@ -39,7 +39,8 @@ module Google
39
39
  :api_format_version,
40
40
  :use_opencensus,
41
41
  :quota_project,
42
- :query)
42
+ :query,
43
+ :add_invocation_id_header)
43
44
 
44
45
  # General client options
45
46
  class ClientOptions
@@ -95,6 +96,8 @@ module Google
95
96
  # @return [String] Project ID to charge quota, or `nil` to default to the credentials-specified project.
96
97
  # @!attribute [rw] query
97
98
  # @return [Hash<String,String>] Additional HTTP URL query parameters to include in requests.
99
+ # @!attribute [rw] add_invocation_id_header
100
+ # @return [Boolean] True if the header gccl-invocation-id need to be set
98
101
 
99
102
  # Get the default options
100
103
  # @return [Google::Apis::RequestOptions]
@@ -129,5 +132,6 @@ module Google
129
132
  RequestOptions.default.api_format_version = nil
130
133
  RequestOptions.default.use_opencensus = true
131
134
  RequestOptions.default.quota_project = nil
135
+ RequestOptions.default.add_invocation_id_header = false
132
136
  end
133
137
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google-apis-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.2
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Google LLC
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-15 00:00:00.000000000 Z
11
+ date: 2022-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: representable
@@ -175,6 +175,7 @@ files:
175
175
  - lib/google/apis/core/logging.rb
176
176
  - lib/google/apis/core/multipart.rb
177
177
  - lib/google/apis/core/storage_download.rb
178
+ - lib/google/apis/core/storage_upload.rb
178
179
  - lib/google/apis/core/upload.rb
179
180
  - lib/google/apis/core/version.rb
180
181
  - lib/google/apis/errors.rb
@@ -185,7 +186,7 @@ licenses:
185
186
  metadata:
186
187
  bug_tracker_uri: https://github.com/googleapis/google-api-ruby-client/issues
187
188
  changelog_uri: https://github.com/googleapis/google-api-ruby-client/tree/main/google-apis-core/CHANGELOG.md
188
- documentation_uri: https://googleapis.dev/ruby/google-apis-core/v0.7.2
189
+ documentation_uri: https://googleapis.dev/ruby/google-apis-core/v0.9.0
189
190
  source_code_uri: https://github.com/googleapis/google-api-ruby-client/tree/main/google-apis-core
190
191
  post_install_message:
191
192
  rdoc_options: []