google-apis-core 0.7.1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4f02ec5d554c69a4510fa74b0b1b4ddf67f7a34fb0d968374952905e44a4a663
4
- data.tar.gz: 2d08a648b8ebdd6679bd602ccef761ee3e1b2418cd008514880912a532d0be33
3
+ metadata.gz: 39e8c0ee69956045fad35dd99b60187bee9a559e66c31141784f69c938b828da
4
+ data.tar.gz: 2bc2f65430050943360436b018b2149f876bdb190d8d637e42d1ac5c908aee41
5
5
  SHA512:
6
- metadata.gz: 7f8bd3f598d3631677a518b3a744bc49ac25913a094678fb930a935e75aae6be445c0a5639a59b72ae33a6e5f8efd1dbafabcfaa210c554aaad325392ccdd7c1
7
- data.tar.gz: 973119aa7df5d7eef5e4a870cd57bcb0980657faaddf408f95beb8962bec169d79811fbd75f3291f73ed12223625cd78833f789b0258ee26ddf42151e1aa2931
6
+ metadata.gz: 26a81d876d54cd42e9e84a4c057297ccd77a1cfebe481de646504f8e30d08496b72141581532dfeae03d3dcb9ff955330b7e94c81bc9bb555130e501fc2879f2
7
+ data.tar.gz: 2c1242fd64e8e66e82b04aa2a4f4c0fb0979e7a0a53f8162836a90a58242f1d46d4b8660101a15c9e82b6b6e48819cdffe5053f90894a9cf1dd5040de2c21db0
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
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
+
15
+ ### 0.7.2 (2022-09-15)
16
+
17
+ #### Bug Fixes
18
+
19
+ * do not reset query_values in case of form encoding ([#11654](https://github.com/googleapis/google-api-ruby-client/issues/11654))
20
+
3
21
  ### 0.7.1 (2022-09-14)
4
22
 
5
23
  #### 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
@@ -168,7 +172,6 @@ module Google
168
172
  @form_encoded = true
169
173
  self.body = Addressable::URI.form_encode(url.query_values(Array))
170
174
  self.header['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'
171
- self.url.query_values = {}
172
175
  else
173
176
  @form_encoded = false
174
177
  end
@@ -217,7 +220,7 @@ module Google
217
220
  def check_status(status, header = nil, body = nil, message = nil)
218
221
  # TODO: 304 Not Modified depends on context...
219
222
  case status
220
- when 200...300
223
+ when 200...300, 308
221
224
  nil
222
225
  when 301, 302, 303, 307
223
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.1".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.1
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-14 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.1
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: []