aws-sdk-s3 1.48.0 → 1.183.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.
Files changed (134) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1352 -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 +1005 -106
  8. data/lib/aws-sdk-s3/bucket_acl.rb +65 -18
  9. data/lib/aws-sdk-s3/bucket_cors.rb +80 -18
  10. data/lib/aws-sdk-s3/bucket_lifecycle.rb +71 -20
  11. data/lib/aws-sdk-s3/bucket_lifecycle_configuration.rb +126 -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 +108 -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 +14517 -941
  21. data/lib/aws-sdk-s3/client_api.rb +1296 -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 +716 -0
  61. data/lib/aws-sdk-s3/endpoints.rb +1434 -0
  62. data/lib/aws-sdk-s3/errors.rb +170 -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 +161 -46
  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 +104 -27
  71. data/lib/aws-sdk-s3/multipart_stream_uploader.rb +61 -21
  72. data/lib/aws-sdk-s3/multipart_upload.rb +342 -32
  73. data/lib/aws-sdk-s3/multipart_upload_error.rb +2 -0
  74. data/lib/aws-sdk-s3/multipart_upload_part.rb +384 -46
  75. data/lib/aws-sdk-s3/object.rb +2600 -231
  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 +2174 -204
  80. data/lib/aws-sdk-s3/object_version.rb +539 -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/checksum_algorithm.rb +31 -0
  87. data/lib/aws-sdk-s3/plugins/dualstack.rb +7 -50
  88. data/lib/aws-sdk-s3/plugins/endpoints.rb +86 -0
  89. data/lib/aws-sdk-s3/plugins/expect_100_continue.rb +5 -4
  90. data/lib/aws-sdk-s3/plugins/express_session_auth.rb +88 -0
  91. data/lib/aws-sdk-s3/plugins/get_bucket_location_fix.rb +3 -1
  92. data/lib/aws-sdk-s3/plugins/http_200_errors.rb +62 -17
  93. data/lib/aws-sdk-s3/plugins/iad_regional_endpoint.rb +44 -0
  94. data/lib/aws-sdk-s3/plugins/location_constraint.rb +5 -1
  95. data/lib/aws-sdk-s3/plugins/md5s.rb +14 -70
  96. data/lib/aws-sdk-s3/plugins/redirects.rb +2 -0
  97. data/lib/aws-sdk-s3/plugins/s3_host_id.rb +2 -0
  98. data/lib/aws-sdk-s3/plugins/s3_signer.rb +63 -94
  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 +141 -62
  104. data/lib/aws-sdk-s3/resource.rb +156 -17
  105. data/lib/aws-sdk-s3/types.rb +13021 -4106
  106. data/lib/aws-sdk-s3/waiters.rb +67 -1
  107. data/lib/aws-sdk-s3.rb +46 -32
  108. data/sig/bucket.rbs +222 -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 +2472 -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 +42 -0
  125. data/sig/multipart_upload.rbs +120 -0
  126. data/sig/multipart_upload_part.rbs +109 -0
  127. data/sig/object.rbs +459 -0
  128. data/sig/object_acl.rbs +86 -0
  129. data/sig/object_summary.rbs +345 -0
  130. data/sig/object_version.rbs +143 -0
  131. data/sig/resource.rbs +134 -0
  132. data/sig/types.rbs +2712 -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, CRC64NVME
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
255
+ # be used as a message integrity check to verify that the request body
256
+ # was 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)