aws-sdk-s3 1.199.1 → 1.202.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.
@@ -13,8 +13,8 @@ module Aws
13
13
  # @option options [Client] :client
14
14
  # @option options [Integer] :multipart_threshold (104857600)
15
15
  def initialize(options = {})
16
- @options = options
17
16
  @client = options[:client] || Client.new
17
+ @executor = options[:executor]
18
18
  @multipart_threshold = options[:multipart_threshold] || DEFAULT_MULTIPART_THRESHOLD
19
19
  end
20
20
 
@@ -36,11 +36,9 @@ module Aws
36
36
  # @return [void]
37
37
  def upload(source, options = {})
38
38
  Aws::Plugins::UserAgent.metric('S3_TRANSFER') do
39
- if File.size(source) >= multipart_threshold
40
- MultipartFileUploader.new(@options).upload(source, options)
39
+ if File.size(source) >= @multipart_threshold
40
+ MultipartFileUploader.new(client: @client, executor: @executor).upload(source, options)
41
41
  else
42
- # remove multipart parameters not supported by put_object
43
- options.delete(:thread_count)
44
42
  put_object(source, options)
45
43
  end
46
44
  end
@@ -48,9 +46,9 @@ module Aws
48
46
 
49
47
  private
50
48
 
51
- def open_file(source)
52
- if String === source || Pathname === source
53
- File.open(source, 'rb') { |file| yield(file) }
49
+ def open_file(source, &block)
50
+ if source.is_a?(String) || source.is_a?(Pathname)
51
+ File.open(source, 'rb', &block)
54
52
  else
55
53
  yield(source)
56
54
  end
@@ -7,10 +7,8 @@ module Aws
7
7
  module S3
8
8
  # @api private
9
9
  class MultipartFileUploader
10
-
11
10
  MIN_PART_SIZE = 5 * 1024 * 1024 # 5MB
12
11
  MAX_PARTS = 10_000
13
- DEFAULT_THREAD_COUNT = 10
14
12
  CREATE_OPTIONS = Set.new(Client.api.operation(:create_multipart_upload).input.shape.member_names)
15
13
  COMPLETE_OPTIONS = Set.new(Client.api.operation(:complete_multipart_upload).input.shape.member_names)
16
14
  UPLOAD_PART_OPTIONS = Set.new(Client.api.operation(:upload_part).input.shape.member_names)
@@ -21,10 +19,9 @@ module Aws
21
19
  )
22
20
 
23
21
  # @option options [Client] :client
24
- # @option options [Integer] :thread_count (DEFAULT_THREAD_COUNT)
25
22
  def initialize(options = {})
26
23
  @client = options[:client] || Client.new
27
- @thread_count = options[:thread_count] || DEFAULT_THREAD_COUNT
24
+ @executor = options[:executor]
28
25
  end
29
26
 
30
27
  # @return [Client]
@@ -38,11 +35,12 @@ module Aws
38
35
  # It will be invoked with [bytes_read], [total_sizes]
39
36
  # @return [Seahorse::Client::Response] - the CompleteMultipartUploadResponse
40
37
  def upload(source, options = {})
41
- raise ArgumentError, 'unable to multipart upload files smaller than 5MB' if File.size(source) < MIN_PART_SIZE
38
+ file_size = File.size(source)
39
+ raise ArgumentError, 'unable to multipart upload files smaller than 5MB' if file_size < MIN_PART_SIZE
42
40
 
43
41
  upload_id = initiate_upload(options)
44
- parts = upload_parts(upload_id, source, options)
45
- complete_upload(upload_id, parts, source, options)
42
+ parts = upload_parts(upload_id, source, file_size, options)
43
+ complete_upload(upload_id, parts, file_size, options)
46
44
  end
47
45
 
48
46
  private
@@ -51,22 +49,21 @@ module Aws
51
49
  @client.create_multipart_upload(create_opts(options)).upload_id
52
50
  end
53
51
 
54
- def complete_upload(upload_id, parts, source, options)
52
+ def complete_upload(upload_id, parts, file_size, options)
55
53
  @client.complete_multipart_upload(
56
- **complete_opts(options).merge(
57
- upload_id: upload_id,
58
- multipart_upload: { parts: parts },
59
- mpu_object_size: File.size(source)
60
- )
54
+ **complete_opts(options),
55
+ upload_id: upload_id,
56
+ multipart_upload: { parts: parts },
57
+ mpu_object_size: file_size
61
58
  )
62
59
  rescue StandardError => e
63
60
  abort_upload(upload_id, options, [e])
64
61
  end
65
62
 
66
- def upload_parts(upload_id, source, options)
63
+ def upload_parts(upload_id, source, file_size, options)
67
64
  completed = PartList.new
68
- pending = PartList.new(compute_parts(upload_id, source, options))
69
- errors = upload_in_threads(pending, completed, options)
65
+ pending = PartList.new(compute_parts(upload_id, source, file_size, options))
66
+ errors = upload_with_executor(pending, completed, options)
70
67
  if errors.empty?
71
68
  completed.to_a.sort_by { |part| part[:part_number] }
72
69
  else
@@ -81,22 +78,25 @@ module Aws
81
78
  rescue MultipartUploadError => e
82
79
  raise e
83
80
  rescue StandardError => e
84
- msg = "failed to abort multipart upload: #{e.message}. "\
85
- "Multipart upload failed: #{errors.map(&:message).join('; ')}"
81
+ msg = "failed to abort multipart upload: #{e.message}. " \
82
+ "Multipart upload failed: #{errors.map(&:message).join('; ')}"
86
83
  raise MultipartUploadError.new(msg, errors + [e])
87
84
  end
88
85
 
89
- def compute_parts(upload_id, source, options)
90
- size = File.size(source)
91
- default_part_size = compute_default_part_size(size)
86
+ def compute_parts(upload_id, source, file_size, options)
87
+ default_part_size = compute_default_part_size(file_size)
92
88
  offset = 0
93
89
  part_number = 1
94
90
  parts = []
95
- while offset < size
91
+ while offset < file_size
96
92
  parts << upload_part_opts(options).merge(
97
93
  upload_id: upload_id,
98
94
  part_number: part_number,
99
- body: FilePart.new(source: source, offset: offset, size: part_size(size, default_part_size, offset))
95
+ body: FilePart.new(
96
+ source: source,
97
+ offset: offset,
98
+ size: part_size(file_size, default_part_size, offset)
99
+ )
100
100
  )
101
101
  part_number += 1
102
102
  offset += default_part_size
@@ -112,20 +112,23 @@ module Aws
112
112
  keys.any? { |key| checksum_key?(key) }
113
113
  end
114
114
 
115
+ def checksum_not_required?(options)
116
+ @client.config.request_checksum_calculation == 'when_required' && !options[:checksum_algorithm]
117
+ end
118
+
115
119
  def create_opts(options)
116
- opts = { checksum_algorithm: Aws::Plugins::ChecksumAlgorithm::DEFAULT_CHECKSUM }
117
- opts[:checksum_type] = 'FULL_OBJECT' if has_checksum_key?(options.keys)
118
- CREATE_OPTIONS.each_with_object(opts) do |key, hash|
119
- hash[key] = options[key] if options.key?(key)
120
+ opts = {}
121
+ unless checksum_not_required?(options)
122
+ opts[:checksum_algorithm] = Aws::Plugins::ChecksumAlgorithm::DEFAULT_CHECKSUM
120
123
  end
124
+ opts[:checksum_type] = 'FULL_OBJECT' if has_checksum_key?(options.keys)
125
+ CREATE_OPTIONS.each_with_object(opts) { |k, h| h[k] = options[k] if options.key?(k) }
121
126
  end
122
127
 
123
128
  def complete_opts(options)
124
129
  opts = {}
125
130
  opts[:checksum_type] = 'FULL_OBJECT' if has_checksum_key?(options.keys)
126
- COMPLETE_OPTIONS.each_with_object(opts) do |key, hash|
127
- hash[key] = options[key] if options.key?(key)
128
- end
131
+ COMPLETE_OPTIONS.each_with_object(opts) { |k, h| h[k] = options[k] if options.key?(k) }
129
132
  end
130
133
 
131
134
  def upload_part_opts(options)
@@ -135,43 +138,45 @@ module Aws
135
138
  end
136
139
  end
137
140
 
138
- def upload_in_threads(pending, completed, options)
139
- threads = []
140
- if (callback = options[:progress_callback])
141
- progress = MultipartProgress.new(pending, callback)
142
- end
143
- options.fetch(:thread_count, @thread_count).times do
144
- thread = Thread.new do
145
- begin
146
- while (part = pending.shift)
147
- if progress
148
- part[:on_chunk_sent] =
149
- proc do |_chunk, bytes, _total|
150
- progress.call(part[:part_number], bytes)
151
- end
152
- end
153
- resp = @client.upload_part(part)
154
- part[:body].close
155
- completed_part = { etag: resp.etag, part_number: part[:part_number] }
156
- algorithm = resp.context.params[:checksum_algorithm]
157
- k = "checksum_#{algorithm.downcase}".to_sym
158
- completed_part[k] = resp.send(k)
159
- completed.push(completed_part)
160
- end
161
- nil
162
- rescue StandardError => e
163
- # keep other threads from uploading other parts
164
- pending.clear!
165
- e
166
- end
141
+ def upload_with_executor(pending, completed, options)
142
+ upload_attempts = 0
143
+ completion_queue = Queue.new
144
+ abort_upload = false
145
+ errors = []
146
+ progress = MultipartProgress.new(pending, options[:progress_callback])
147
+
148
+ while (part = pending.shift)
149
+ break if abort_upload
150
+
151
+ upload_attempts += 1
152
+ @executor.post(part) do |p|
153
+ update_progress(progress, p)
154
+ resp = @client.upload_part(p)
155
+ p[:body].close
156
+ completed_part = { etag: resp.etag, part_number: p[:part_number] }
157
+ apply_part_checksum(resp, completed_part)
158
+ completed.push(completed_part)
159
+ rescue StandardError => e
160
+ abort_upload = true
161
+ errors << e
162
+ ensure
163
+ completion_queue << :done
167
164
  end
168
- threads << thread
169
165
  end
170
- threads.map(&:value).compact
166
+
167
+ upload_attempts.times { completion_queue.pop }
168
+ errors
171
169
  end
172
170
 
173
- def compute_default_part_size(source_size)
174
- [(source_size.to_f / MAX_PARTS).ceil, MIN_PART_SIZE].max.to_i
171
+ def apply_part_checksum(resp, part)
172
+ return unless (checksum = resp.context.params[:checksum_algorithm])
173
+
174
+ k = :"checksum_#{checksum.downcase}"
175
+ part[k] = resp.send(k)
176
+ end
177
+
178
+ def compute_default_part_size(file_size)
179
+ [(file_size.to_f / MAX_PARTS).ceil, MIN_PART_SIZE].max.to_i
175
180
  end
176
181
 
177
182
  def part_size(total_size, part_size, offset)
@@ -182,6 +187,15 @@ module Aws
182
187
  end
183
188
  end
184
189
 
190
+ def update_progress(progress, part)
191
+ return unless progress.progress_callback
192
+
193
+ part[:on_chunk_sent] =
194
+ proc do |_chunk, bytes, _total|
195
+ progress.call(part[:part_number], bytes)
196
+ end
197
+ end
198
+
185
199
  # @api private
186
200
  class PartList
187
201
  def initialize(parts = [])
@@ -222,6 +236,8 @@ module Aws
222
236
  @progress_callback = progress_callback
223
237
  end
224
238
 
239
+ attr_reader :progress_callback
240
+
225
241
  def call(part_number, bytes_read)
226
242
  # part numbers start at 1
227
243
  @bytes_sent[part_number - 1] = bytes_read
@@ -11,7 +11,6 @@ module Aws
11
11
  class MultipartStreamUploader
12
12
 
13
13
  DEFAULT_PART_SIZE = 5 * 1024 * 1024 # 5MB
14
- DEFAULT_THREAD_COUNT = 10
15
14
  CREATE_OPTIONS = Set.new(Client.api.operation(:create_multipart_upload).input.shape.member_names)
16
15
  UPLOAD_PART_OPTIONS = Set.new(Client.api.operation(:upload_part).input.shape.member_names)
17
16
  COMPLETE_UPLOAD_OPTIONS = Set.new(Client.api.operation(:complete_multipart_upload).input.shape.member_names)
@@ -19,9 +18,9 @@ module Aws
19
18
  # @option options [Client] :client
20
19
  def initialize(options = {})
21
20
  @client = options[:client] || Client.new
21
+ @executor = options[:executor]
22
22
  @tempfile = options[:tempfile]
23
23
  @part_size = options[:part_size] || DEFAULT_PART_SIZE
24
- @thread_count = options[:thread_count] || DEFAULT_THREAD_COUNT
25
24
  end
26
25
 
27
26
  # @return [Client]
@@ -29,7 +28,6 @@ module Aws
29
28
 
30
29
  # @option options [required,String] :bucket
31
30
  # @option options [required,String] :key
32
- # @option options [Integer] :thread_count (DEFAULT_THREAD_COUNT)
33
31
  # @return [Seahorse::Client::Response] - the CompleteMultipartUploadResponse
34
32
  def upload(options = {}, &block)
35
33
  Aws::Plugins::UserAgent.metric('S3_TRANSFER') do
@@ -54,28 +52,30 @@ module Aws
54
52
  end
55
53
 
56
54
  def upload_parts(upload_id, options, &block)
57
- completed = Queue.new
58
- thread_errors = []
59
- errors = begin
55
+ completed_parts = Queue.new
56
+ errors = []
57
+
58
+ begin
60
59
  IO.pipe do |read_pipe, write_pipe|
61
- threads = upload_in_threads(
62
- read_pipe,
63
- completed,
64
- upload_part_opts(options).merge(upload_id: upload_id),
65
- thread_errors
66
- )
67
- begin
68
- block.call(write_pipe)
69
- ensure
70
- # Ensure the pipe is closed to avoid https://github.com/jruby/jruby/issues/6111
71
- write_pipe.close
60
+ upload_thread = Thread.new do
61
+ upload_with_executor(
62
+ read_pipe,
63
+ completed_parts,
64
+ errors,
65
+ upload_part_opts(options).merge(upload_id: upload_id)
66
+ )
72
67
  end
73
- threads.map(&:value).compact
68
+
69
+ block.call(write_pipe)
70
+ ensure
71
+ # Ensure the pipe is closed to avoid https://github.com/jruby/jruby/issues/6111
72
+ write_pipe.close
73
+ upload_thread.join
74
74
  end
75
75
  rescue StandardError => e
76
- thread_errors + [e]
76
+ errors << e
77
77
  end
78
- return ordered_parts(completed) if errors.empty?
78
+ return ordered_parts(completed_parts) if errors.empty?
79
79
 
80
80
  abort_upload(upload_id, options, errors)
81
81
  end
@@ -128,37 +128,34 @@ module Aws
128
128
  end
129
129
  end
130
130
 
131
- def upload_in_threads(read_pipe, completed, options, thread_errors)
132
- mutex = Mutex.new
131
+ def upload_with_executor(read_pipe, completed, errors, options)
132
+ completion_queue = Queue.new
133
+ queued_parts = 0
133
134
  part_number = 0
134
- options.fetch(:thread_count, @thread_count).times.map do
135
- thread = Thread.new do
136
- loop do
137
- body, thread_part_number = mutex.synchronize do
138
- [read_to_part_body(read_pipe), part_number += 1]
139
- end
140
- break unless body || thread_part_number == 1
141
-
142
- begin
143
- part = options.merge(body: body, part_number: thread_part_number)
144
- resp = @client.upload_part(part)
145
- completed_part = create_completed_part(resp, part)
146
- completed.push(completed_part)
147
- ensure
148
- clear_body(body)
149
- end
150
- end
151
- nil
135
+ mutex = Mutex.new
136
+ loop do
137
+ part_body, current_part_num = mutex.synchronize do
138
+ [read_to_part_body(read_pipe), part_number += 1]
139
+ end
140
+ break unless part_body || current_part_num == 1
141
+
142
+ queued_parts += 1
143
+ @executor.post(part_body, current_part_num, options) do |body, num, opts|
144
+ part = opts.merge(body: body, part_number: num)
145
+ resp = @client.upload_part(part)
146
+ completed_part = create_completed_part(resp, part)
147
+ completed.push(completed_part)
152
148
  rescue StandardError => e
153
- # keep other threads from uploading other parts
154
149
  mutex.synchronize do
155
- thread_errors.push(e)
150
+ errors.push(e)
156
151
  read_pipe.close_read unless read_pipe.closed?
157
152
  end
158
- e
153
+ ensure
154
+ clear_body(body)
155
+ completion_queue << :done
159
156
  end
160
- thread
161
157
  end
158
+ queued_parts.times { completion_queue.pop }
162
159
  end
163
160
 
164
161
  def create_completed_part(resp, part)
@@ -136,10 +136,10 @@ module Aws::S3
136
136
  end
137
137
 
138
138
  # The Base64 encoded, 32-bit `CRC32 checksum` of the object. This
139
- # checksum is only be present if the checksum was uploaded with the
140
- # object. When you use an API operation on an object that was uploaded
141
- # using multipart uploads, this value may not be a direct checksum value
142
- # of the full object. Instead, it's a calculation based on the checksum
139
+ # checksum is only present if the checksum was uploaded with the object.
140
+ # When you use an API operation on an object that was uploaded using
141
+ # multipart uploads, this value may not be a direct checksum value of
142
+ # the full object. Instead, it's a calculation based on the checksum
143
143
  # values of each individual part. For more information about how
144
144
  # checksums are calculated with multipart uploads, see [ Checking object
145
145
  # integrity][1] in the *Amazon S3 User Guide*.
@@ -181,8 +181,8 @@ module Aws::S3
181
181
  data[:checksum_crc64nvme]
182
182
  end
183
183
 
184
- # The Base64 encoded, 160-bit `SHA1` digest of the object. This will
185
- # only be present if the object was uploaded with the object. When you
184
+ # The Base64 encoded, 160-bit `SHA1` digest of the object. This checksum
185
+ # is only present if the checksum was uploaded with the object. When you
186
186
  # use the API operation on an object that was uploaded using multipart
187
187
  # uploads, this value may not be a direct checksum value of the full
188
188
  # object. Instead, it's a calculation based on the checksum values of
@@ -198,14 +198,14 @@ module Aws::S3
198
198
  data[:checksum_sha1]
199
199
  end
200
200
 
201
- # The Base64 encoded, 256-bit `SHA256` digest of the object. This will
202
- # only be present if the object was uploaded with the object. When you
203
- # use an API operation on an object that was uploaded using multipart
204
- # uploads, this value may not be a direct checksum value of the full
205
- # object. Instead, it's a calculation based on the checksum values of
206
- # each individual part. For more information about how checksums are
207
- # calculated with multipart uploads, see [ Checking object integrity][1]
208
- # in the *Amazon S3 User Guide*.
201
+ # The Base64 encoded, 256-bit `SHA256` digest of the object. This
202
+ # checksum is only present if the checksum was uploaded with the object.
203
+ # When you use an API operation on an object that was uploaded using
204
+ # multipart uploads, this value may not be a direct checksum value of
205
+ # the full object. Instead, it's a calculation based on the checksum
206
+ # values of each individual part. For more information about how
207
+ # checksums are calculated with multipart uploads, see [ Checking object
208
+ # integrity][1] in the *Amazon S3 User Guide*.
209
209
  #
210
210
  #
211
211
  #
@@ -757,6 +757,8 @@ module Aws::S3
757
757
  # grant_read: "GrantRead",
758
758
  # grant_read_acp: "GrantReadACP",
759
759
  # grant_write_acp: "GrantWriteACP",
760
+ # if_match: "IfMatch",
761
+ # if_none_match: "IfNoneMatch",
760
762
  # metadata: {
761
763
  # "MetadataKey" => "MetadataValue",
762
764
  # },
@@ -1013,6 +1015,35 @@ module Aws::S3
1013
1015
  # * This functionality is not supported for Amazon S3 on Outposts.
1014
1016
  #
1015
1017
  # </note>
1018
+ # @option options [String] :if_match
1019
+ # Copies the object if the entity tag (ETag) of the destination object
1020
+ # matches the specified tag. If the ETag values do not match, the
1021
+ # operation returns a `412 Precondition Failed` error. If a concurrent
1022
+ # operation occurs during the upload S3 returns a `409
1023
+ # ConditionalRequestConflict` response. On a 409 failure you should
1024
+ # fetch the object's ETag and retry the upload.
1025
+ #
1026
+ # Expects the ETag value as a string.
1027
+ #
1028
+ # For more information about conditional requests, see [RFC 7232][1].
1029
+ #
1030
+ #
1031
+ #
1032
+ # [1]: https://tools.ietf.org/html/rfc7232
1033
+ # @option options [String] :if_none_match
1034
+ # Copies the object only if the object key name at the destination does
1035
+ # not already exist in the bucket specified. Otherwise, Amazon S3
1036
+ # returns a `412 Precondition Failed` error. If a concurrent operation
1037
+ # occurs during the upload S3 returns a `409 ConditionalRequestConflict`
1038
+ # response. On a 409 failure you should retry the upload.
1039
+ #
1040
+ # Expects the '*' (asterisk) character.
1041
+ #
1042
+ # For more information about conditional requests, see [RFC 7232][1].
1043
+ #
1044
+ #
1045
+ #
1046
+ # [1]: https://tools.ietf.org/html/rfc7232
1016
1047
  # @option options [Hash<String,String>] :metadata
1017
1048
  # A map of metadata to store with the object in S3.
1018
1049
  # @option options [String] :metadata_directive
@@ -1535,17 +1566,15 @@ module Aws::S3
1535
1566
  # you provide does not match the actual owner of the bucket, the request
1536
1567
  # fails with the HTTP status code `403 Forbidden` (access denied).
1537
1568
  # @option options [String] :if_match
1538
- # The `If-Match` header field makes the request method conditional on
1539
- # ETags. If the ETag value does not match, the operation returns a `412
1540
- # Precondition Failed` error. If the ETag matches or if the object
1541
- # doesn't exist, the operation will return a `204 Success (No Content)
1542
- # response`.
1543
- #
1544
- # For more information about conditional requests, see [RFC 7232][1].
1569
+ # Deletes the object if the ETag (entity tag) value provided during the
1570
+ # delete operation matches the ETag of the object in S3. If the ETag
1571
+ # values do not match, the operation returns a `412 Precondition Failed`
1572
+ # error.
1545
1573
  #
1546
- # <note markdown="1"> This functionality is only supported for directory buckets.
1574
+ # Expects the ETag value as a string. `If-Match` does accept a string
1575
+ # value of an '*' (asterisk) character to denote a match of any ETag.
1547
1576
  #
1548
- # </note>
1577
+ # For more information about conditional requests, see [RFC 7232][1].
1549
1578
  #
1550
1579
  #
1551
1580
  #
@@ -354,6 +354,8 @@ module Aws::S3
354
354
  # grant_read: "GrantRead",
355
355
  # grant_read_acp: "GrantReadACP",
356
356
  # grant_write_acp: "GrantWriteACP",
357
+ # if_match: "IfMatch",
358
+ # if_none_match: "IfNoneMatch",
357
359
  # metadata: {
358
360
  # "MetadataKey" => "MetadataValue",
359
361
  # },
@@ -610,6 +612,35 @@ module Aws::S3
610
612
  # * This functionality is not supported for Amazon S3 on Outposts.
611
613
  #
612
614
  # </note>
615
+ # @option options [String] :if_match
616
+ # Copies the object if the entity tag (ETag) of the destination object
617
+ # matches the specified tag. If the ETag values do not match, the
618
+ # operation returns a `412 Precondition Failed` error. If a concurrent
619
+ # operation occurs during the upload S3 returns a `409
620
+ # ConditionalRequestConflict` response. On a 409 failure you should
621
+ # fetch the object's ETag and retry the upload.
622
+ #
623
+ # Expects the ETag value as a string.
624
+ #
625
+ # For more information about conditional requests, see [RFC 7232][1].
626
+ #
627
+ #
628
+ #
629
+ # [1]: https://tools.ietf.org/html/rfc7232
630
+ # @option options [String] :if_none_match
631
+ # Copies the object only if the object key name at the destination does
632
+ # not already exist in the bucket specified. Otherwise, Amazon S3
633
+ # returns a `412 Precondition Failed` error. If a concurrent operation
634
+ # occurs during the upload S3 returns a `409 ConditionalRequestConflict`
635
+ # response. On a 409 failure you should retry the upload.
636
+ #
637
+ # Expects the '*' (asterisk) character.
638
+ #
639
+ # For more information about conditional requests, see [RFC 7232][1].
640
+ #
641
+ #
642
+ #
643
+ # [1]: https://tools.ietf.org/html/rfc7232
613
644
  # @option options [Hash<String,String>] :metadata
614
645
  # A map of metadata to store with the object in S3.
615
646
  # @option options [String] :metadata_directive
@@ -1132,17 +1163,15 @@ module Aws::S3
1132
1163
  # you provide does not match the actual owner of the bucket, the request
1133
1164
  # fails with the HTTP status code `403 Forbidden` (access denied).
1134
1165
  # @option options [String] :if_match
1135
- # The `If-Match` header field makes the request method conditional on
1136
- # ETags. If the ETag value does not match, the operation returns a `412
1137
- # Precondition Failed` error. If the ETag matches or if the object
1138
- # doesn't exist, the operation will return a `204 Success (No Content)
1139
- # response`.
1166
+ # Deletes the object if the ETag (entity tag) value provided during the
1167
+ # delete operation matches the ETag of the object in S3. If the ETag
1168
+ # values do not match, the operation returns a `412 Precondition Failed`
1169
+ # error.
1140
1170
  #
1141
- # For more information about conditional requests, see [RFC 7232][1].
1171
+ # Expects the ETag value as a string. `If-Match` does accept a string
1172
+ # value of an '*' (asterisk) character to denote a match of any ETag.
1142
1173
  #
1143
- # <note markdown="1"> This functionality is only supported for directory buckets.
1144
- #
1145
- # </note>
1174
+ # For more information about conditional requests, see [RFC 7232][1].
1146
1175
  #
1147
1176
  #
1148
1177
  #
@@ -312,17 +312,15 @@ module Aws::S3
312
312
  # you provide does not match the actual owner of the bucket, the request
313
313
  # fails with the HTTP status code `403 Forbidden` (access denied).
314
314
  # @option options [String] :if_match
315
- # The `If-Match` header field makes the request method conditional on
316
- # ETags. If the ETag value does not match, the operation returns a `412
317
- # Precondition Failed` error. If the ETag matches or if the object
318
- # doesn't exist, the operation will return a `204 Success (No Content)
319
- # response`.
320
- #
321
- # For more information about conditional requests, see [RFC 7232][1].
315
+ # Deletes the object if the ETag (entity tag) value provided during the
316
+ # delete operation matches the ETag of the object in S3. If the ETag
317
+ # values do not match, the operation returns a `412 Precondition Failed`
318
+ # error.
322
319
  #
323
- # <note markdown="1"> This functionality is only supported for directory buckets.
320
+ # Expects the ETag value as a string. `If-Match` does accept a string
321
+ # value of an '*' (asterisk) character to denote a match of any ETag.
324
322
  #
325
- # </note>
323
+ # For more information about conditional requests, see [RFC 7232][1].
326
324
  #
327
325
  #
328
326
  #
@@ -25,7 +25,7 @@ The endpoint provider used to resolve endpoints. Any object that responds to
25
25
 
26
26
  option(
27
27
  :disable_s3_express_session_auth,
28
- doc_type: 'Boolean',
28
+ doc_type: 'boolean',
29
29
  docstring: <<~DOCS) do |cfg|
30
30
  Parameter to indicate whether S3Express session auth should be disabled
31
31
  DOCS