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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ce67af03cec391ae12f32828eb7c0df504eb7d04e0b92694aac6adf98d4f31d8
4
- data.tar.gz: fd5227cea10440d966385242ab7330f4e686c4c0bb74f6d98a99e815286b04f4
3
+ metadata.gz: 5d024f53c9ef6e0174ec201b40ed2d437fc17fa8e98ef9d154e9cc9bf62540a1
4
+ data.tar.gz: aa5a7b80813d3f3ad8bb89c732aec0ef6defa631f1f3c3710c94366d1f584346
5
5
  SHA512:
6
- metadata.gz: 647712dad491d16745a70a63e2dc808c43f98f63853a58ef8d46b7f620f73f0b3116668f43a79b1f4819bab988e83c64e33952b877b396bf8c600fbe88a6983a
7
- data.tar.gz: 670c0199907867b49f6db7bd8b25a7d6cc2760cab4d57038314adf13e51119513a3968e78394e15ad9f09ed69fbfa3a5fb2633a44f802eac9da4e842f2a37065
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 client
153
- # @return [HTTPClient]
154
- attr_accessor :client
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 client
267
- # @return [HTTPClient]
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 client
516
- # @return [HTTPClient]
545
+ # Create a new HTTP connection
546
+ # @return [Faraday::Connection]
517
547
  def new_client
518
- client = ::HTTPClient.new
519
-
520
- if client_options.transparent_gzip_decompression
521
- client.transparent_gzip_decompression = client_options.transparent_gzip_decompression
522
- end
523
-
524
- client.proxy = client_options.proxy_url if client_options.proxy_url
525
-
526
- if client_options.open_timeout_sec
527
- client.connect_timeout = client_options.open_timeout_sec
548
+ options = {}
549
+ request_options = {params_encoder: Faraday::FlatParamsEncoder}
550
+ options[:proxy] = {uri: client_options.proxy_url} if client_options.proxy_url
551
+ request_options[:open_timeout] = client_options.open_timeout_sec if client_options.open_timeout_sec
552
+ request_options[:read_timeout] = client_options.read_timeout_sec if client_options.read_timeout_sec
553
+ request_options[:write_timeout] = client_options.send_timeout_sec if client_options.send_timeout_sec
554
+ options[:request] = request_options unless request_options.empty?
555
+ options[:headers] = { 'User-Agent' => user_agent }
556
+
557
+ Faraday.new options do |faraday|
558
+ faraday.response :logger, Google::Apis.logger if client_options.log_http_requests
559
+ faraday.response :follow_redirects_google_apis_core, limit: 5
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 header from the body in an HTTP response.
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<(HTTP::Message::Headers, String)>]
219
- # the header and the body, separately.
218
+ # @return [Array<(Hash{String=>Array<String>}, String)>]
219
+ # the headers and the body, separately.
220
220
  def split_header_and_body(response)
221
- header = HTTP::Message::Headers.new
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
- header[match[1]] = match.post_match
229
+ (headers[match[1]] ||= []) << match.post_match
230
230
  end
231
- [header, payload]
231
+ [headers, payload]
232
232
  end
233
233
  end
234
234
  end
@@ -42,7 +42,7 @@ module Google
42
42
  end
43
43
 
44
44
  def read(length = nil, buf = nil)
45
- buf = buf ? buf.replace('') : ''
45
+ buf = buf ? buf.replace('') : +''
46
46
 
47
47
  begin
48
48
  io = @ios[@index]
@@ -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 [HTTPClient] client
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
- query: query,
83
- header: request_header,
84
- follow_redirect: true) do |res, chunk|
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
+ # 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
- download_offset ||= (status == 206 ? @offset : 0)
89
- download_offset += chunk.bytesize
90
+ # HTTP 206 is Partial Content
91
+ download_offset ||= (status == 206 ? @offset : 0)
92
+ download_offset += chunk.bytesize
90
93
 
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
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
- # logger.debug { sprintf('Writing chunk (%d bytes, %d total)', chunk.length, bytes_read) }
101
- @download_io.write(next_chunk)
103
+ # logger.debug { sprintf('Writing chunk (%d bytes, %d total)', chunk.length, bytes_read) }
104
+ @download_io.write(next_chunk)
102
105
 
103
- @offset += next_chunk.bytesize
106
+ @offset += next_chunk.bytesize
107
+ end
104
108
  end
105
109
 
106
- @download_io.flush if @download_io.respond_to?(:flush)
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.header, http_res.body)
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
- # HTTP Client
63
- # @return [HTTPClient]
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 [HTTPClient] client
100
- # HTTP client
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 = '' unless 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?(HTTPClient::BadResponseError)
288
- begin
289
- res = err.res
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) || 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 [HTTPClient] client
306
- # HTTP client
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.request(method.to_s.upcase,
319
- url.to_s,
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.header, @http_res.body)
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
- if body.respond_to? :bytesize
409
- @opencensus_span.put_message_event \
410
- OpenCensus::Trace::SpanBuilder::SENT, 1, body.bytesize
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 [HTTPClient] client
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
- query: query,
52
- header: request_header,
53
- follow_redirect: true) do |res, chunk|
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
+ # 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
- download_offset ||= (status == 206 ? @offset : 0)
58
- download_offset += chunk.bytesize
57
+ download_offset ||= (status == 206 ? @offset : 0)
58
+ download_offset += chunk.bytesize
59
59
 
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
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
- # logger.debug { sprintf('Writing chunk (%d bytes, %d total)', chunk.length, bytes_read) }
70
- @download_io.write(next_chunk)
69
+ # logger.debug { sprintf('Writing chunk (%d bytes, %d total)', chunk.length, bytes_read) }
70
+ @download_io.write(next_chunk)
71
71
 
72
- @offset += next_chunk.bytesize
72
+ @offset += next_chunk.bytesize
73
+ end
73
74
  end
74
75
 
75
- @download_io.flush if @download_io.respond_to?(:flush)
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.header, http_res.body)
83
- # In case of file download in storage, we need to respond back with http
84
- # header along with the actual object.
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 [HTTPClient] client
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, query: request_query,
125
- body: body,
126
- header: request_header,
127
- follow_redirect: true)
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 [HTTPClient] client
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, body: chunk_body, header: request_header, follow_redirect: true)
186
+ response = client.put(@upload_url, chunk_body, request_header)
157
187
 
158
- result = process_response(response.status_code, response.header, response.body)
159
- @upload_incomplete = false if response.status_code.eql? OK_STATUS
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
- @upload_url = header[LOCATION_HEADER].first unless header[LOCATION_HEADER].empty?
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
- @offset = Integer(header[BYTES_RECEIVED_HEADER].first) unless header[BYTES_RECEIVED_HEADER].empty?
163
- @upload_url = header[UPLOAD_URL_HEADER].first unless header[UPLOAD_URL_HEADER].empty?
164
- upload_status = header[UPLOAD_STATUS_HEADER].first
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.request(method.to_s.upcase,
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 [HTTPClient] client
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, body: '', header: request_header, follow_redirect: true)
207
+ client.post(@upload_url, '', request_header)
210
208
  end
211
209
 
212
210
 
213
211
  # Send the actual content
214
212
  #
215
- # @param [HTTPClient] client
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, body: content, header: request_header, follow_redirect: true)
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 [HTTPClient] client
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.status_code, response.header, response.body)
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.status_code, response.header, response.body)
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.status_code, response.header, response.body)
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
@@ -16,7 +16,7 @@ module Google
16
16
  module Apis
17
17
  module Core
18
18
  # Core version
19
- VERSION = "0.15.0".freeze
19
+ VERSION = "1.0.2".freeze
20
20
  end
21
21
  end
22
22
  end
@@ -43,7 +43,7 @@ module Google
43
43
  end
44
44
 
45
45
  def inspect
46
- extra = ""
46
+ extra = +""
47
47
  extra << " status_code: #{status_code.inspect}" unless status_code.nil?
48
48
  extra << " header: #{header.inspect}" unless header.nil?
49
49
  extra << " body: #{body.inspect}" unless body.nil?
@@ -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
- # @return [Boolean] True if gzip compression needs to be enabled
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.15.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: 2024-05-13 00:00:00.000000000 Z
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: 4.a
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: 4.a
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.5'
46
+ version: '2.8'
54
47
  - - ">="
55
48
  - !ruby/object:Gem::Version
56
- version: 2.5.1
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.5'
56
+ version: '2.8'
64
57
  - - ">="
65
58
  - !ruby/object:Gem::Version
66
- version: 2.5.1
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.0'
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.0'
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.9'
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.9'
87
+ version: '1.14'
95
88
  - !ruby/object:Gem::Dependency
96
- name: httpclient
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: 3.a
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: 3.a
101
+ version: '2.13'
115
102
  - !ruby/object:Gem::Dependency
116
- name: rexml
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/v0.15.0
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: '2.7'
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.5.6
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: []