aws-sdk-s3 1.48.0 → 1.169.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1270 -0
  3. data/LICENSE.txt +202 -0
  4. data/VERSION +1 -0
  5. data/lib/aws-sdk-s3/access_grants_credentials.rb +57 -0
  6. data/lib/aws-sdk-s3/access_grants_credentials_provider.rb +250 -0
  7. data/lib/aws-sdk-s3/bucket.rb +959 -106
  8. data/lib/aws-sdk-s3/bucket_acl.rb +64 -18
  9. data/lib/aws-sdk-s3/bucket_cors.rb +79 -18
  10. data/lib/aws-sdk-s3/bucket_lifecycle.rb +66 -20
  11. data/lib/aws-sdk-s3/bucket_lifecycle_configuration.rb +106 -21
  12. data/lib/aws-sdk-s3/bucket_logging.rb +68 -16
  13. data/lib/aws-sdk-s3/bucket_notification.rb +52 -20
  14. data/lib/aws-sdk-s3/bucket_policy.rb +107 -17
  15. data/lib/aws-sdk-s3/bucket_region_cache.rb +11 -5
  16. data/lib/aws-sdk-s3/bucket_request_payment.rb +60 -15
  17. data/lib/aws-sdk-s3/bucket_tagging.rb +71 -18
  18. data/lib/aws-sdk-s3/bucket_versioning.rb +133 -17
  19. data/lib/aws-sdk-s3/bucket_website.rb +78 -21
  20. data/lib/aws-sdk-s3/client.rb +13765 -1019
  21. data/lib/aws-sdk-s3/client_api.rb +1137 -197
  22. data/lib/aws-sdk-s3/customizations/bucket.rb +56 -37
  23. data/lib/aws-sdk-s3/customizations/errors.rb +40 -0
  24. data/lib/aws-sdk-s3/customizations/multipart_upload.rb +2 -0
  25. data/lib/aws-sdk-s3/customizations/object.rb +288 -68
  26. data/lib/aws-sdk-s3/customizations/object_summary.rb +10 -0
  27. data/lib/aws-sdk-s3/customizations/object_version.rb +13 -0
  28. data/lib/aws-sdk-s3/customizations/types/list_object_versions_output.rb +2 -0
  29. data/lib/aws-sdk-s3/customizations/types/permanent_redirect.rb +26 -0
  30. data/lib/aws-sdk-s3/customizations.rb +27 -28
  31. data/lib/aws-sdk-s3/encryption/client.rb +28 -7
  32. data/lib/aws-sdk-s3/encryption/decrypt_handler.rb +71 -29
  33. data/lib/aws-sdk-s3/encryption/default_cipher_provider.rb +43 -5
  34. data/lib/aws-sdk-s3/encryption/default_key_provider.rb +2 -0
  35. data/lib/aws-sdk-s3/encryption/encrypt_handler.rb +13 -2
  36. data/lib/aws-sdk-s3/encryption/errors.rb +2 -0
  37. data/lib/aws-sdk-s3/encryption/io_auth_decrypter.rb +2 -0
  38. data/lib/aws-sdk-s3/encryption/io_decrypter.rb +11 -3
  39. data/lib/aws-sdk-s3/encryption/io_encrypter.rb +2 -0
  40. data/lib/aws-sdk-s3/encryption/key_provider.rb +2 -0
  41. data/lib/aws-sdk-s3/encryption/kms_cipher_provider.rb +46 -11
  42. data/lib/aws-sdk-s3/encryption/materials.rb +8 -6
  43. data/lib/aws-sdk-s3/encryption/utils.rb +25 -0
  44. data/lib/aws-sdk-s3/encryption.rb +4 -0
  45. data/lib/aws-sdk-s3/encryptionV2/client.rb +570 -0
  46. data/lib/aws-sdk-s3/encryptionV2/decrypt_handler.rb +223 -0
  47. data/lib/aws-sdk-s3/encryptionV2/default_cipher_provider.rb +170 -0
  48. data/lib/aws-sdk-s3/encryptionV2/default_key_provider.rb +40 -0
  49. data/lib/aws-sdk-s3/encryptionV2/encrypt_handler.rb +65 -0
  50. data/lib/aws-sdk-s3/encryptionV2/errors.rb +37 -0
  51. data/lib/aws-sdk-s3/encryptionV2/io_auth_decrypter.rb +58 -0
  52. data/lib/aws-sdk-s3/encryptionV2/io_decrypter.rb +37 -0
  53. data/lib/aws-sdk-s3/encryptionV2/io_encrypter.rb +73 -0
  54. data/lib/aws-sdk-s3/encryptionV2/key_provider.rb +31 -0
  55. data/lib/aws-sdk-s3/encryptionV2/kms_cipher_provider.rb +173 -0
  56. data/lib/aws-sdk-s3/encryptionV2/materials.rb +60 -0
  57. data/lib/aws-sdk-s3/encryptionV2/utils.rb +103 -0
  58. data/lib/aws-sdk-s3/encryption_v2.rb +23 -0
  59. data/lib/aws-sdk-s3/endpoint_parameters.rb +181 -0
  60. data/lib/aws-sdk-s3/endpoint_provider.rb +592 -0
  61. data/lib/aws-sdk-s3/endpoints.rb +1392 -0
  62. data/lib/aws-sdk-s3/errors.rb +126 -1
  63. data/lib/aws-sdk-s3/event_streams.rb +8 -1
  64. data/lib/aws-sdk-s3/express_credentials.rb +55 -0
  65. data/lib/aws-sdk-s3/express_credentials_provider.rb +59 -0
  66. data/lib/aws-sdk-s3/file_downloader.rb +176 -44
  67. data/lib/aws-sdk-s3/file_part.rb +11 -6
  68. data/lib/aws-sdk-s3/file_uploader.rb +39 -18
  69. data/lib/aws-sdk-s3/legacy_signer.rb +17 -25
  70. data/lib/aws-sdk-s3/multipart_file_uploader.rb +82 -23
  71. data/lib/aws-sdk-s3/multipart_stream_uploader.rb +61 -21
  72. data/lib/aws-sdk-s3/multipart_upload.rb +265 -32
  73. data/lib/aws-sdk-s3/multipart_upload_error.rb +2 -0
  74. data/lib/aws-sdk-s3/multipart_upload_part.rb +367 -45
  75. data/lib/aws-sdk-s3/object.rb +2475 -228
  76. data/lib/aws-sdk-s3/object_acl.rb +103 -25
  77. data/lib/aws-sdk-s3/object_copier.rb +9 -5
  78. data/lib/aws-sdk-s3/object_multipart_copier.rb +48 -22
  79. data/lib/aws-sdk-s3/object_summary.rb +2075 -203
  80. data/lib/aws-sdk-s3/object_version.rb +492 -80
  81. data/lib/aws-sdk-s3/plugins/accelerate.rb +17 -64
  82. data/lib/aws-sdk-s3/plugins/access_grants.rb +178 -0
  83. data/lib/aws-sdk-s3/plugins/arn.rb +70 -0
  84. data/lib/aws-sdk-s3/plugins/bucket_dns.rb +7 -43
  85. data/lib/aws-sdk-s3/plugins/bucket_name_restrictions.rb +20 -3
  86. data/lib/aws-sdk-s3/plugins/dualstack.rb +7 -50
  87. data/lib/aws-sdk-s3/plugins/endpoints.rb +86 -0
  88. data/lib/aws-sdk-s3/plugins/expect_100_continue.rb +5 -4
  89. data/lib/aws-sdk-s3/plugins/express_session_auth.rb +97 -0
  90. data/lib/aws-sdk-s3/plugins/get_bucket_location_fix.rb +3 -1
  91. data/lib/aws-sdk-s3/plugins/http_200_errors.rb +60 -15
  92. data/lib/aws-sdk-s3/plugins/iad_regional_endpoint.rb +44 -0
  93. data/lib/aws-sdk-s3/plugins/location_constraint.rb +5 -1
  94. data/lib/aws-sdk-s3/plugins/md5s.rb +35 -30
  95. data/lib/aws-sdk-s3/plugins/redirects.rb +2 -0
  96. data/lib/aws-sdk-s3/plugins/s3_host_id.rb +2 -0
  97. data/lib/aws-sdk-s3/plugins/s3_signer.rb +63 -94
  98. data/lib/aws-sdk-s3/plugins/skip_whole_multipart_get_checksums.rb +31 -0
  99. data/lib/aws-sdk-s3/plugins/sse_cpk.rb +3 -1
  100. data/lib/aws-sdk-s3/plugins/streaming_retry.rb +139 -0
  101. data/lib/aws-sdk-s3/plugins/url_encoded_keys.rb +2 -0
  102. data/lib/aws-sdk-s3/presigned_post.rb +160 -99
  103. data/lib/aws-sdk-s3/presigner.rb +138 -59
  104. data/lib/aws-sdk-s3/resource.rb +155 -17
  105. data/lib/aws-sdk-s3/types.rb +12229 -4377
  106. data/lib/aws-sdk-s3/waiters.rb +67 -1
  107. data/lib/aws-sdk-s3.rb +46 -32
  108. data/sig/bucket.rbs +216 -0
  109. data/sig/bucket_acl.rbs +78 -0
  110. data/sig/bucket_cors.rbs +69 -0
  111. data/sig/bucket_lifecycle.rbs +88 -0
  112. data/sig/bucket_lifecycle_configuration.rbs +115 -0
  113. data/sig/bucket_logging.rbs +76 -0
  114. data/sig/bucket_notification.rbs +114 -0
  115. data/sig/bucket_policy.rbs +59 -0
  116. data/sig/bucket_request_payment.rbs +54 -0
  117. data/sig/bucket_tagging.rbs +65 -0
  118. data/sig/bucket_versioning.rbs +77 -0
  119. data/sig/bucket_website.rbs +93 -0
  120. data/sig/client.rbs +2406 -0
  121. data/sig/customizations/bucket.rbs +19 -0
  122. data/sig/customizations/object.rbs +38 -0
  123. data/sig/customizations/object_summary.rbs +35 -0
  124. data/sig/errors.rbs +34 -0
  125. data/sig/multipart_upload.rbs +111 -0
  126. data/sig/multipart_upload_part.rbs +105 -0
  127. data/sig/object.rbs +443 -0
  128. data/sig/object_acl.rbs +86 -0
  129. data/sig/object_summary.rbs +335 -0
  130. data/sig/object_version.rbs +137 -0
  131. data/sig/resource.rbs +132 -0
  132. data/sig/types.rbs +2596 -0
  133. data/sig/waiters.rbs +95 -0
  134. metadata +74 -15
@@ -1,11 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # WARNING ABOUT GENERATED CODE
2
4
  #
3
5
  # This file is generated. See the contributing guide for more information:
4
- # https://github.com/aws/aws-sdk-ruby/blob/master/CONTRIBUTING.md
6
+ # https://github.com/aws/aws-sdk-ruby/blob/version-3/CONTRIBUTING.md
5
7
  #
6
8
  # WARNING ABOUT GENERATED CODE
7
9
 
8
10
  module Aws::S3
11
+
9
12
  class ObjectAcl
10
13
 
11
14
  extend Aws::Deprecations
@@ -24,6 +27,7 @@ module Aws::S3
24
27
  @object_key = extract_object_key(args, options)
25
28
  @data = options.delete(:data)
26
29
  @client = options.delete(:client) || Client.new(options)
30
+ @waiter_block_warned = false
27
31
  end
28
32
 
29
33
  # @!group Read-Only Attributes
@@ -38,7 +42,7 @@ module Aws::S3
38
42
  @object_key
39
43
  end
40
44
 
41
-
45
+ # Container for the bucket owner's display name and ID.
42
46
  # @return [Types::Owner]
43
47
  def owner
44
48
  data[:owner]
@@ -52,6 +56,10 @@ module Aws::S3
52
56
 
53
57
  # If present, indicates that the requester was successfully charged for
54
58
  # the request.
59
+ #
60
+ # <note markdown="1"> This functionality is not supported for directory buckets.
61
+ #
62
+ # </note>
55
63
  # @return [String]
56
64
  def request_charged
57
65
  data[:request_charged]
@@ -71,10 +79,12 @@ module Aws::S3
71
79
  #
72
80
  # @return [self]
73
81
  def load
74
- resp = @client.get_object_acl(
82
+ resp = Aws::Plugins::UserAgent.metric('RESOURCE_MODEL') do
83
+ @client.get_object_acl(
75
84
  bucket: @bucket_name,
76
85
  key: @object_key
77
86
  )
87
+ end
78
88
  @data = resp.data
79
89
  self
80
90
  end
@@ -100,7 +110,8 @@ module Aws::S3
100
110
  # Waiter polls an API operation until a resource enters a desired
101
111
  # state.
102
112
  #
103
- # @note The waiting operation is performed on a copy. The original resource remains unchanged
113
+ # @note The waiting operation is performed on a copy. The original resource
114
+ # remains unchanged.
104
115
  #
105
116
  # ## Basic Usage
106
117
  #
@@ -113,13 +124,15 @@ module Aws::S3
113
124
  #
114
125
  # ## Example
115
126
  #
116
- # instance.wait_until(max_attempts:10, delay:5) {|instance| instance.state.name == 'running' }
127
+ # instance.wait_until(max_attempts:10, delay:5) do |instance|
128
+ # instance.state.name == 'running'
129
+ # end
117
130
  #
118
131
  # ## Configuration
119
132
  #
120
133
  # You can configure the maximum number of polling attempts, and the
121
- # delay (in seconds) between each polling attempt. The waiting condition is set
122
- # by passing a block to {#wait_until}:
134
+ # delay (in seconds) between each polling attempt. The waiting condition is
135
+ # set by passing a block to {#wait_until}:
123
136
  #
124
137
  # # poll for ~25 seconds
125
138
  # resource.wait_until(max_attempts:5,delay:5) {|resource|...}
@@ -150,17 +163,16 @@ module Aws::S3
150
163
  # # resource did not enter the desired state in time
151
164
  # end
152
165
  #
166
+ # @yieldparam [Resource] resource to be used in the waiting condition.
153
167
  #
154
- # @yield param [Resource] resource to be used in the waiting condition
155
- #
156
- # @raise [Aws::Waiters::Errors::FailureStateError] Raised when the waiter terminates
157
- # because the waiter has entered a state that it will not transition
158
- # out of, preventing success.
168
+ # @raise [Aws::Waiters::Errors::FailureStateError] Raised when the waiter
169
+ # terminates because the waiter has entered a state that it will not
170
+ # transition out of, preventing success.
159
171
  #
160
172
  # yet successful.
161
173
  #
162
- # @raise [Aws::Waiters::Errors::UnexpectedError] Raised when an error is encountered
163
- # while polling for a resource that is not expected.
174
+ # @raise [Aws::Waiters::Errors::UnexpectedError] Raised when an error is
175
+ # encountered while polling for a resource that is not expected.
164
176
  #
165
177
  # @raise [NotImplementedError] Raised when the resource does not
166
178
  #
@@ -187,7 +199,9 @@ module Aws::S3
187
199
  :retry
188
200
  end
189
201
  end
190
- Aws::Waiters::Waiter.new(options).wait({})
202
+ Aws::Plugins::UserAgent.metric('RESOURCE_MODEL') do
203
+ Aws::Waiters::Waiter.new(options).wait({})
204
+ end
191
205
  end
192
206
 
193
207
  # @!group Actions
@@ -215,6 +229,7 @@ module Aws::S3
215
229
  # },
216
230
  # },
217
231
  # content_md5: "ContentMD5",
232
+ # checksum_algorithm: "CRC32", # accepts CRC32, CRC32C, SHA1, SHA256
218
233
  # grant_full_control: "GrantFullControl",
219
234
  # grant_read: "GrantRead",
220
235
  # grant_read_acp: "GrantReadACP",
@@ -222,41 +237,104 @@ module Aws::S3
222
237
  # grant_write_acp: "GrantWriteACP",
223
238
  # request_payer: "requester", # accepts requester
224
239
  # version_id: "ObjectVersionId",
240
+ # expected_bucket_owner: "AccountId",
225
241
  # })
226
242
  # @param [Hash] options ({})
227
243
  # @option options [String] :acl
228
- # The canned ACL to apply to the object.
244
+ # The canned ACL to apply to the object. For more information, see
245
+ # [Canned ACL][1].
246
+ #
247
+ #
248
+ #
249
+ # [1]: https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#CannedACL
229
250
  # @option options [Types::AccessControlPolicy] :access_control_policy
230
251
  # Contains the elements that set the ACL permissions for an object per
231
252
  # grantee.
232
253
  # @option options [String] :content_md5
254
+ # The base64-encoded 128-bit MD5 digest of the data. This header must be
255
+ # used as a message integrity check to verify that the request body was
256
+ # not corrupted in transit. For more information, go to [RFC
257
+ # 1864.&gt;][1]
258
+ #
259
+ # For requests made using the Amazon Web Services Command Line Interface
260
+ # (CLI) or Amazon Web Services SDKs, this field is calculated
261
+ # automatically.
262
+ #
263
+ #
264
+ #
265
+ # [1]: http://www.ietf.org/rfc/rfc1864.txt
266
+ # @option options [String] :checksum_algorithm
267
+ # Indicates the algorithm used to create the checksum for the object
268
+ # when you use the SDK. This header will not provide any additional
269
+ # functionality if you don't use the SDK. When you send this header,
270
+ # there must be a corresponding `x-amz-checksum` or `x-amz-trailer`
271
+ # header sent. Otherwise, Amazon S3 fails the request with the HTTP
272
+ # status code `400 Bad Request`. For more information, see [Checking
273
+ # object integrity][1] in the *Amazon S3 User Guide*.
274
+ #
275
+ # If you provide an individual checksum, Amazon S3 ignores any provided
276
+ # `ChecksumAlgorithm` parameter.
277
+ #
278
+ #
279
+ #
280
+ # [1]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html
233
281
  # @option options [String] :grant_full_control
234
282
  # Allows grantee the read, write, read ACP, and write ACP permissions on
235
283
  # the bucket.
284
+ #
285
+ # This functionality is not supported for Amazon S3 on Outposts.
236
286
  # @option options [String] :grant_read
237
287
  # Allows grantee to list the objects in the bucket.
288
+ #
289
+ # This functionality is not supported for Amazon S3 on Outposts.
238
290
  # @option options [String] :grant_read_acp
239
291
  # Allows grantee to read the bucket ACL.
292
+ #
293
+ # This functionality is not supported for Amazon S3 on Outposts.
240
294
  # @option options [String] :grant_write
241
- # Allows grantee to create, overwrite, and delete any object in the
242
- # bucket.
295
+ # Allows grantee to create new objects in the bucket.
296
+ #
297
+ # For the bucket and object owners of existing objects, also allows
298
+ # deletions and overwrites of those objects.
243
299
  # @option options [String] :grant_write_acp
244
300
  # Allows grantee to write the ACL for the applicable bucket.
301
+ #
302
+ # This functionality is not supported for Amazon S3 on Outposts.
245
303
  # @option options [String] :request_payer
246
- # Confirms that the requester knows that she or he will be charged for
247
- # the request. Bucket owners need not specify this parameter in their
248
- # requests. Documentation on downloading objects from requester pays
249
- # buckets can be found at
250
- # http://docs.aws.amazon.com/AmazonS3/latest/dev/ObjectsinRequesterPaysBuckets.html
304
+ # Confirms that the requester knows that they will be charged for the
305
+ # request. Bucket owners need not specify this parameter in their
306
+ # requests. If either the source or destination S3 bucket has Requester
307
+ # Pays enabled, the requester will pay for corresponding charges to copy
308
+ # the object. For information about downloading objects from Requester
309
+ # Pays buckets, see [Downloading Objects in Requester Pays Buckets][1]
310
+ # in the *Amazon S3 User Guide*.
311
+ #
312
+ # <note markdown="1"> This functionality is not supported for directory buckets.
313
+ #
314
+ # </note>
315
+ #
316
+ #
317
+ #
318
+ # [1]: https://docs.aws.amazon.com/AmazonS3/latest/dev/ObjectsinRequesterPaysBuckets.html
251
319
  # @option options [String] :version_id
252
- # VersionId used to reference a specific version of the object.
320
+ # Version ID used to reference a specific version of the object.
321
+ #
322
+ # <note markdown="1"> This functionality is not supported for directory buckets.
323
+ #
324
+ # </note>
325
+ # @option options [String] :expected_bucket_owner
326
+ # The account ID of the expected bucket owner. If the account ID that
327
+ # you provide does not match the actual owner of the bucket, the request
328
+ # fails with the HTTP status code `403 Forbidden` (access denied).
253
329
  # @return [Types::PutObjectAclOutput]
254
330
  def put(options = {})
255
331
  options = options.merge(
256
332
  bucket: @bucket_name,
257
333
  key: @object_key
258
334
  )
259
- resp = @client.put_object_acl(options)
335
+ resp = Aws::Plugins::UserAgent.metric('RESOURCE_MODEL') do
336
+ @client.put_object_acl(options)
337
+ end
260
338
  resp.data
261
339
  end
262
340
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'thread'
2
4
 
3
5
  module Aws
@@ -26,11 +28,13 @@ module Aws
26
28
  options[:bucket] = target_bucket
27
29
  options[:key] = target_key
28
30
  options[:copy_source] = copy_source(source)
29
- if options.delete(:multipart_copy)
30
- apply_source_client(source, options)
31
- ObjectMultipartCopier.new(@options).copy(options)
32
- else
33
- @object.client.copy_object(options)
31
+ Aws::Plugins::UserAgent.metric('S3_TRANSFER') do
32
+ if options.delete(:multipart_copy)
33
+ apply_source_client(source, options)
34
+ ObjectMultipartCopier.new(@options).copy(options)
35
+ else
36
+ @object.client.copy_object(options)
37
+ end
34
38
  end
35
39
  end
36
40
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'thread'
2
4
  require 'cgi'
3
5
 
@@ -13,12 +15,18 @@ module Aws
13
15
  MAX_PARTS = 10_000
14
16
 
15
17
  # @option options [Client] :client
16
- # @option [Integer] :min_part_size (52428800) Size of copied parts.
17
- # Defaults to 50MB.
18
- # will be constructed from the given `options' hash.
19
- # @option [Integer] :thread_count (10) Number of concurrent threads to
20
- # use for copying parts.
18
+ # @option options [Integer] :min_part_size (52428800)
19
+ # Size of copied parts. Defaults to 50MB.
20
+ # @option options [Integer] :thread_count (10) Number of concurrent
21
+ # threads to use for copying parts.
22
+ # @option options [Boolean] :use_source_parts (false) Use part sizes
23
+ # defined on the source object if any exist. If copying or moving an
24
+ # object that is already multipart, this does not re-part the object,
25
+ # instead re-using the part definitions on the original. That means
26
+ # the etag and any checksums will not change. This is especially
27
+ # useful if the source object has parts with varied sizes.
21
28
  def initialize(options = {})
29
+ @use_source_parts = options.delete(:use_source_parts) || false
22
30
  @thread_count = options.delete(:thread_count) || 10
23
31
  @min_part_size = options.delete(:min_part_size) || (FIVE_MB * 10)
24
32
  @client = options[:client] || Client.new
@@ -29,8 +37,9 @@ module Aws
29
37
 
30
38
  # @option (see S3::Client#copy_object)
31
39
  def copy(options = {})
32
- size = source_size(options)
33
- options[:upload_id] = initiate_upload(options)
40
+ metadata = source_metadata(options)
41
+ size = metadata[:content_length]
42
+ options[:upload_id] = initiate_upload(metadata.merge(options))
34
43
  begin
35
44
  parts = copy_parts(size, default_part_size(size), options)
36
45
  complete_upload(parts, options)
@@ -72,10 +81,9 @@ module Aws
72
81
  end
73
82
 
74
83
  def copy_part(part)
75
- {
76
- etag: @client.upload_part_copy(part).copy_part_result.etag,
77
- part_number: part[:part_number],
78
- }
84
+ @client.upload_part_copy(part).copy_part_result.to_h.merge({
85
+ part_number: part[:part_number]
86
+ }).tap { |result| result.delete(:last_modified) }
79
87
  end
80
88
 
81
89
  def complete_upload(parts, options)
@@ -98,26 +106,39 @@ module Aws
98
106
  parts = []
99
107
  options = options_for(:upload_part_copy, options)
100
108
  while offset < size
109
+ part_size = calculate_part_size(part_number, default_part_size, options)
101
110
  parts << options.merge({
102
111
  part_number: part_number,
103
- copy_source_range: byte_range(offset, default_part_size, size),
112
+ copy_source_range: byte_range(offset, part_size, size),
104
113
  })
105
114
  part_number += 1
106
- offset += default_part_size
115
+ offset += part_size
107
116
  end
108
117
  parts
109
118
  end
110
119
 
111
- def byte_range(offset, default_part_size, size)
112
- if offset + default_part_size < size
113
- "bytes=#{offset}-#{offset + default_part_size - 1}"
120
+ def byte_range(offset, part_size, size)
121
+ if offset + part_size < size
122
+ "bytes=#{offset}-#{offset + part_size - 1}"
114
123
  else
115
124
  "bytes=#{offset}-#{size - 1}"
116
125
  end
117
126
  end
118
127
 
119
- def source_size(options)
120
- return options.delete(:content_length) if options[:content_length]
128
+ def calculate_part_size(part_number, default_part_size, options)
129
+ if @use_source_parts && source_has_parts(options)
130
+ source_metadata(options.merge({ part_number: part_number }))[:content_length]
131
+ else
132
+ default_part_size
133
+ end
134
+ end
135
+
136
+ def source_has_parts(options)
137
+ @source_has_parts ||= source_metadata(options.merge({ part_number: 1 }))[:parts_count]
138
+ end
139
+
140
+ def source_metadata(options)
141
+ return options.slice(:content_length) if options[:content_length]
121
142
 
122
143
  client = options[:copy_source_client] || @client
123
144
 
@@ -127,10 +148,15 @@ module Aws
127
148
  bucket, key = options[:copy_source].match(/([^\/]+?)\/(.+)/)[1,2]
128
149
  end
129
150
 
130
- key = CGI.unescape(key)
131
- opts = { bucket: bucket, key: key }
132
- opts[:version_id] = version_id if version_id
133
- client.head_object(opts).content_length
151
+ head_opts = { bucket: bucket, key: CGI.unescape(key) }.tap { |opts|
152
+ opts[:version_id] = version_id if version_id
153
+ opts[:part_number] = options[:part_number] if options[:part_number]
154
+ }
155
+
156
+ client.head_object(head_opts).to_h.tap { |head|
157
+ head.delete(:server_side_encryption)
158
+ head.delete(:ssekms_key_id)
159
+ }
134
160
  end
135
161
 
136
162
  def default_part_size(source_size)