aws-sdk-s3 1.48.0 → 1.113.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +888 -0
  3. data/LICENSE.txt +202 -0
  4. data/VERSION +1 -0
  5. data/lib/aws-sdk-s3/arn/access_point_arn.rb +69 -0
  6. data/lib/aws-sdk-s3/arn/multi_region_access_point_arn.rb +68 -0
  7. data/lib/aws-sdk-s3/arn/object_lambda_arn.rb +69 -0
  8. data/lib/aws-sdk-s3/arn/outpost_access_point_arn.rb +74 -0
  9. data/lib/aws-sdk-s3/bucket.rb +375 -82
  10. data/lib/aws-sdk-s3/bucket_acl.rb +55 -15
  11. data/lib/aws-sdk-s3/bucket_cors.rb +67 -14
  12. data/lib/aws-sdk-s3/bucket_lifecycle.rb +54 -16
  13. data/lib/aws-sdk-s3/bucket_lifecycle_configuration.rb +56 -16
  14. data/lib/aws-sdk-s3/bucket_logging.rb +52 -13
  15. data/lib/aws-sdk-s3/bucket_notification.rb +43 -17
  16. data/lib/aws-sdk-s3/bucket_policy.rb +51 -13
  17. data/lib/aws-sdk-s3/bucket_region_cache.rb +2 -0
  18. data/lib/aws-sdk-s3/bucket_request_payment.rb +51 -12
  19. data/lib/aws-sdk-s3/bucket_tagging.rb +59 -14
  20. data/lib/aws-sdk-s3/bucket_versioning.rb +118 -12
  21. data/lib/aws-sdk-s3/bucket_website.rb +66 -17
  22. data/lib/aws-sdk-s3/client.rb +8973 -740
  23. data/lib/aws-sdk-s3/client_api.rb +778 -2
  24. data/lib/aws-sdk-s3/customizations/bucket.rb +59 -16
  25. data/lib/aws-sdk-s3/customizations/multipart_upload.rb +2 -0
  26. data/lib/aws-sdk-s3/customizations/object.rb +200 -62
  27. data/lib/aws-sdk-s3/customizations/object_summary.rb +5 -0
  28. data/lib/aws-sdk-s3/customizations/types/list_object_versions_output.rb +2 -0
  29. data/lib/aws-sdk-s3/customizations.rb +4 -1
  30. data/lib/aws-sdk-s3/encryption/client.rb +22 -5
  31. data/lib/aws-sdk-s3/encryption/decrypt_handler.rb +71 -29
  32. data/lib/aws-sdk-s3/encryption/default_cipher_provider.rb +43 -5
  33. data/lib/aws-sdk-s3/encryption/default_key_provider.rb +2 -0
  34. data/lib/aws-sdk-s3/encryption/encrypt_handler.rb +13 -2
  35. data/lib/aws-sdk-s3/encryption/errors.rb +2 -0
  36. data/lib/aws-sdk-s3/encryption/io_auth_decrypter.rb +2 -0
  37. data/lib/aws-sdk-s3/encryption/io_decrypter.rb +11 -3
  38. data/lib/aws-sdk-s3/encryption/io_encrypter.rb +2 -0
  39. data/lib/aws-sdk-s3/encryption/key_provider.rb +2 -0
  40. data/lib/aws-sdk-s3/encryption/kms_cipher_provider.rb +34 -3
  41. data/lib/aws-sdk-s3/encryption/materials.rb +8 -6
  42. data/lib/aws-sdk-s3/encryption/utils.rb +25 -0
  43. data/lib/aws-sdk-s3/encryption.rb +4 -0
  44. data/lib/aws-sdk-s3/encryptionV2/client.rb +566 -0
  45. data/lib/aws-sdk-s3/encryptionV2/decrypt_handler.rb +222 -0
  46. data/lib/aws-sdk-s3/encryptionV2/default_cipher_provider.rb +170 -0
  47. data/lib/aws-sdk-s3/encryptionV2/default_key_provider.rb +40 -0
  48. data/lib/aws-sdk-s3/encryptionV2/encrypt_handler.rb +65 -0
  49. data/lib/aws-sdk-s3/encryptionV2/errors.rb +37 -0
  50. data/lib/aws-sdk-s3/encryptionV2/io_auth_decrypter.rb +58 -0
  51. data/lib/aws-sdk-s3/encryptionV2/io_decrypter.rb +37 -0
  52. data/lib/aws-sdk-s3/encryptionV2/io_encrypter.rb +73 -0
  53. data/lib/aws-sdk-s3/encryptionV2/key_provider.rb +31 -0
  54. data/lib/aws-sdk-s3/encryptionV2/kms_cipher_provider.rb +169 -0
  55. data/lib/aws-sdk-s3/encryptionV2/materials.rb +60 -0
  56. data/lib/aws-sdk-s3/encryptionV2/utils.rb +103 -0
  57. data/lib/aws-sdk-s3/encryption_v2.rb +23 -0
  58. data/lib/aws-sdk-s3/errors.rb +123 -1
  59. data/lib/aws-sdk-s3/event_streams.rb +8 -1
  60. data/lib/aws-sdk-s3/file_downloader.rb +17 -10
  61. data/lib/aws-sdk-s3/file_part.rb +11 -6
  62. data/lib/aws-sdk-s3/file_uploader.rb +33 -14
  63. data/lib/aws-sdk-s3/legacy_signer.rb +17 -25
  64. data/lib/aws-sdk-s3/multipart_file_uploader.rb +78 -19
  65. data/lib/aws-sdk-s3/multipart_stream_uploader.rb +18 -7
  66. data/lib/aws-sdk-s3/multipart_upload.rb +178 -29
  67. data/lib/aws-sdk-s3/multipart_upload_error.rb +2 -0
  68. data/lib/aws-sdk-s3/multipart_upload_part.rb +233 -42
  69. data/lib/aws-sdk-s3/object.rb +846 -179
  70. data/lib/aws-sdk-s3/object_acl.rb +79 -21
  71. data/lib/aws-sdk-s3/object_copier.rb +2 -0
  72. data/lib/aws-sdk-s3/object_multipart_copier.rb +2 -0
  73. data/lib/aws-sdk-s3/object_summary.rb +611 -162
  74. data/lib/aws-sdk-s3/object_version.rb +162 -71
  75. data/lib/aws-sdk-s3/plugins/accelerate.rb +38 -38
  76. data/lib/aws-sdk-s3/plugins/arn.rb +254 -0
  77. data/lib/aws-sdk-s3/plugins/bucket_dns.rb +8 -8
  78. data/lib/aws-sdk-s3/plugins/bucket_name_restrictions.rb +25 -3
  79. data/lib/aws-sdk-s3/plugins/dualstack.rb +38 -33
  80. data/lib/aws-sdk-s3/plugins/expect_100_continue.rb +4 -4
  81. data/lib/aws-sdk-s3/plugins/get_bucket_location_fix.rb +3 -1
  82. data/lib/aws-sdk-s3/plugins/http_200_errors.rb +11 -3
  83. data/lib/aws-sdk-s3/plugins/iad_regional_endpoint.rb +73 -0
  84. data/lib/aws-sdk-s3/plugins/location_constraint.rb +2 -0
  85. data/lib/aws-sdk-s3/plugins/md5s.rb +34 -30
  86. data/lib/aws-sdk-s3/plugins/object_lambda_endpoint.rb +25 -0
  87. data/lib/aws-sdk-s3/plugins/redirects.rb +2 -0
  88. data/lib/aws-sdk-s3/plugins/s3_host_id.rb +2 -0
  89. data/lib/aws-sdk-s3/plugins/s3_signer.rb +89 -36
  90. data/lib/aws-sdk-s3/plugins/skip_whole_multipart_get_checksums.rb +31 -0
  91. data/lib/aws-sdk-s3/plugins/sse_cpk.rb +3 -1
  92. data/lib/aws-sdk-s3/plugins/streaming_retry.rb +118 -0
  93. data/lib/aws-sdk-s3/plugins/url_encoded_keys.rb +2 -0
  94. data/lib/aws-sdk-s3/presigned_post.rb +110 -51
  95. data/lib/aws-sdk-s3/presigner.rb +133 -45
  96. data/lib/aws-sdk-s3/resource.rb +43 -7
  97. data/lib/aws-sdk-s3/types.rb +8437 -1132
  98. data/lib/aws-sdk-s3/waiters.rb +67 -1
  99. data/lib/aws-sdk-s3.rb +12 -6
  100. metadata +37 -12
@@ -0,0 +1,254 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../arn/access_point_arn'
4
+ require_relative '../arn/object_lambda_arn'
5
+ require_relative '../arn/outpost_access_point_arn'
6
+ require_relative '../arn/multi_region_access_point_arn'
7
+
8
+ module Aws
9
+ module S3
10
+ module Plugins
11
+ # When an accesspoint ARN is provided for :bucket in S3 operations, this
12
+ # plugin resolves the request endpoint from the ARN when possible.
13
+ # @api private
14
+ class ARN < Seahorse::Client::Plugin
15
+ option(
16
+ :s3_use_arn_region,
17
+ default: true,
18
+ doc_type: 'Boolean',
19
+ docstring: <<-DOCS) do |cfg|
20
+ For S3 ARNs passed into the `:bucket` parameter, this option will
21
+ use the region in the ARN, allowing for cross-region requests to
22
+ be made. Set to `false` to use the client's region instead.
23
+ DOCS
24
+ resolve_s3_use_arn_region(cfg)
25
+ end
26
+
27
+ option(
28
+ :s3_disable_multiregion_access_points,
29
+ default: false,
30
+ doc_type: 'Boolean',
31
+ docstring: <<-DOCS) do |cfg|
32
+ When set to `false` this will option will raise errors when multi-region
33
+ access point ARNs are used. Multi-region access points can potentially
34
+ result in cross region requests.
35
+ DOCS
36
+ resolve_s3_disable_multiregion_access_points(cfg)
37
+ end
38
+
39
+ # param validator is validate:50
40
+ # endpoint is build:90 (populates the URI for the first time)
41
+ # endpoint pattern is build:10
42
+ def add_handlers(handlers, _config)
43
+ handlers.add(ARNHandler, step: :validate, priority: 75)
44
+ handlers.add(UrlHandler)
45
+ end
46
+
47
+ # After extracting out any ARN input, resolve a new URL with it.
48
+ class UrlHandler < Seahorse::Client::Handler
49
+ def call(context)
50
+ if context.metadata[:s3_arn]
51
+ ARN.resolve_url!(
52
+ context.http_request.endpoint,
53
+ context.metadata[:s3_arn][:arn],
54
+ context.metadata[:s3_arn][:resolved_region],
55
+ context.metadata[:s3_arn][:fips],
56
+ context.metadata[:s3_arn][:dualstack],
57
+ # if regional_endpoint is false, a custom endpoint was provided
58
+ # in this case, we want to prefix the endpoint using the ARN
59
+ !context.config.regional_endpoint
60
+ )
61
+ end
62
+ @handler.call(context)
63
+ end
64
+ end
65
+
66
+ # This plugin will extract out any ARN input and set context for other
67
+ # plugins to use without having to translate the ARN again.
68
+ class ARNHandler < Seahorse::Client::Handler
69
+ def call(context)
70
+ bucket_member = _bucket_member(context.operation.input.shape)
71
+ if bucket_member && (bucket = context.params[bucket_member])
72
+ resolved_region, arn = ARN.resolve_arn!(
73
+ bucket,
74
+ context.config.region,
75
+ context.config.s3_use_arn_region
76
+ )
77
+ if arn
78
+ validate_config!(context, arn)
79
+
80
+ context.metadata[:s3_arn] = {
81
+ arn: arn,
82
+ resolved_region: resolved_region,
83
+ fips: context.config.use_fips_endpoint,
84
+ dualstack: extract_dualstack_config!(context)
85
+ }
86
+ end
87
+ end
88
+ @handler.call(context)
89
+ end
90
+
91
+ private
92
+
93
+ def _bucket_member(input)
94
+ input.members.each do |member, ref|
95
+ return member if ref.shape.name == 'BucketName'
96
+ end
97
+ nil
98
+ end
99
+
100
+ # other plugins use dualstack so disable it when we're done
101
+ def extract_dualstack_config!(context)
102
+ dualstack = context[:use_dualstack_endpoint]
103
+ context[:use_dualstack_endpoint] = false if dualstack
104
+ dualstack
105
+ end
106
+
107
+ def validate_config!(context, arn)
108
+ if context.config.force_path_style
109
+ raise ArgumentError,
110
+ 'Cannot provide an Access Point ARN when '\
111
+ '`:force_path_style` is set to true.'
112
+ end
113
+
114
+ if context.config.use_accelerate_endpoint
115
+ raise ArgumentError,
116
+ 'Cannot provide an Access Point ARN when '\
117
+ '`:use_accelerate_endpoint` is set to true.'
118
+ end
119
+
120
+ if !arn.support_dualstack? && context[:use_dualstack_endpoint]
121
+ raise ArgumentError,
122
+ 'Cannot provide an Outpost Access Point, Object Lambda, '\
123
+ 'or Multi-region Access Point ARN'\
124
+ ' when `:use_dualstack_endpoint` is set to true.'
125
+ end
126
+
127
+ if arn.region.empty? && context.config.s3_disable_multiregion_access_points
128
+ raise ArgumentError,
129
+ 'Cannot provide a Multi-region Access Point ARN with '\
130
+ '`:s3_disable_multiregion_access_points` set to true'
131
+ end
132
+
133
+ if context.config.use_fips_endpoint && !arn.support_fips?
134
+ raise ArgumentError,
135
+ 'FIPS client regions are not supported for this type '\
136
+ 'of ARN.'
137
+ end
138
+ end
139
+ end
140
+
141
+ class << self
142
+ # @api private
143
+ def resolve_arn!(member_value, region, use_arn_region)
144
+ if Aws::ARNParser.arn?(member_value)
145
+ arn = Aws::ARNParser.parse(member_value)
146
+ s3_arn = resolve_arn_type!(arn)
147
+ s3_arn.validate_arn!
148
+ validate_region_config!(s3_arn, region, use_arn_region)
149
+ region = s3_arn.region if use_arn_region
150
+ [region, s3_arn]
151
+ else
152
+ [region]
153
+ end
154
+ end
155
+
156
+ # @api private
157
+ def resolve_url!(url, arn, region, fips = false, dualstack = false, has_custom_endpoint = false)
158
+ custom_endpoint = url.host if has_custom_endpoint
159
+ url.host = arn.host_url(region, fips, dualstack, custom_endpoint)
160
+ url.path = url_path(url.path, arn)
161
+ url
162
+ end
163
+
164
+ private
165
+
166
+ def resolve_arn_type!(arn)
167
+ case arn.service
168
+ when 's3'
169
+ arn.region.empty? ?
170
+ Aws::S3::MultiRegionAccessPointARN.new(arn.to_h) :
171
+ Aws::S3::AccessPointARN.new(arn.to_h)
172
+ when 's3-outposts'
173
+ Aws::S3::OutpostAccessPointARN.new(arn.to_h)
174
+ when 's3-object-lambda'
175
+ Aws::S3::ObjectLambdaARN.new(arn.to_h)
176
+ else
177
+ raise ArgumentError,
178
+ 'Only Access Point, Outposts, and Object Lambdas ARNs '\
179
+ 'are currently supported.'
180
+ end
181
+ end
182
+
183
+ def resolve_s3_use_arn_region(cfg)
184
+ value = ENV['AWS_S3_USE_ARN_REGION'] ||
185
+ Aws.shared_config.s3_use_arn_region(profile: cfg.profile) ||
186
+ 'true'
187
+ value = Aws::Util.str_2_bool(value)
188
+ # Raise if provided value is not true or false
189
+ if value.nil?
190
+ raise ArgumentError,
191
+ 'Must provide either `true` or `false` for the '\
192
+ '`s3_use_arn_region` profile option or for '\
193
+ "ENV['AWS_S3_USE_ARN_REGION']."
194
+ end
195
+ value
196
+ end
197
+
198
+ def resolve_s3_disable_multiregion_access_points(cfg)
199
+ value = ENV['AWS_S3_DISABLE_MULTIREGION_ACCESS_POINTS'] ||
200
+ Aws.shared_config.s3_disable_multiregion_access_points(profile: cfg.profile) ||
201
+ 'false'
202
+ value = Aws::Util.str_2_bool(value)
203
+ # Raise if provided value is not true or false
204
+ if value.nil?
205
+ raise ArgumentError,
206
+ 'Must provide either `true` or `false` for '\
207
+ 's3_use_arn_region profile option or for '\
208
+ "ENV['AWS_S3_USE_ARN_REGION']"
209
+ end
210
+ value
211
+ end
212
+
213
+ # Remove ARN from the path because we've already set the new host
214
+ def url_path(path, arn)
215
+ path = path.sub("/#{Seahorse::Util.uri_escape(arn.to_s)}", '')
216
+ .sub("/#{arn}", '')
217
+ "/#{path}" unless path =~ /^\//
218
+ path
219
+ end
220
+
221
+ def validate_region_config!(arn, region, use_arn_region)
222
+ if ['s3-external-1', 'aws-global'].include?(region)
223
+ # These "regions" are not regional endpoints
224
+ unless use_arn_region
225
+ raise Aws::Errors::InvalidARNRegionError,
226
+ 'Configured client region is not a regional endpoint.'
227
+ end
228
+ # These "regions" are in the AWS partition
229
+ # Cannot use ARN region unless it's the same partition
230
+ unless arn.partition == 'aws'
231
+ raise Aws::Errors::InvalidARNPartitionError
232
+ end
233
+ else
234
+ # use_arn_region does not apply to MRAP (global) arns
235
+ unless arn.region.empty?
236
+ # Raise if the ARN and client regions are in different partitions
237
+ if use_arn_region &&
238
+ !Aws::Partitions.partition(arn.partition).region?(region)
239
+ raise Aws::Errors::InvalidARNPartitionError
240
+ end
241
+
242
+ # Raise if regions mismatch
243
+ # Either when it's a fips client or not using the ARN region
244
+ if !use_arn_region && region != arn.region
245
+ raise Aws::Errors::InvalidARNRegionError
246
+ end
247
+ end
248
+ end
249
+ end
250
+ end
251
+ end
252
+ end
253
+ end
254
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws
2
4
  module S3
3
5
  module Plugins
@@ -22,7 +24,7 @@ request URI and never moved to the host as a sub-domain.
22
24
  DOCS
23
25
 
24
26
  def add_handlers(handlers, config)
25
- handlers.add(Handler) unless config.force_path_style
27
+ handlers.add(Handler, priority: 48) unless config.force_path_style
26
28
  end
27
29
 
28
30
  # @api private
@@ -38,11 +40,9 @@ request URI and never moved to the host as a sub-domain.
38
40
  def move_dns_compat_bucket_to_subdomain(context)
39
41
  bucket_name = context.params[:bucket]
40
42
  endpoint = context.http_request.endpoint
41
- if
42
- bucket_name &&
43
- BucketDns.dns_compatible?(bucket_name, https?(endpoint)) &&
44
- context.operation_name.to_s != 'get_bucket_location'
45
- then
43
+ if bucket_name &&
44
+ BucketDns.dns_compatible?(bucket_name, https?(endpoint)) &&
45
+ context.operation_name.to_s != 'get_bucket_location'
46
46
  move_bucket_to_subdomain(bucket_name, endpoint)
47
47
  end
48
48
  end
@@ -73,8 +73,8 @@ request URI and never moved to the host as a sub-domain.
73
73
  end
74
74
  end
75
75
 
76
- private
77
-
76
+ # @param [String] bucket_name
77
+ # @return [Boolean]
78
78
  def valid_subdomain?(bucket_name)
79
79
  bucket_name.size < 64 &&
80
80
  bucket_name =~ /^[a-z0-9][a-z0-9.-]+[a-z0-9]$/ &&
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws
2
4
  module S3
3
5
  module Plugins
@@ -5,14 +7,34 @@ module Aws
5
7
  class BucketNameRestrictions < Seahorse::Client::Plugin
6
8
  class Handler < Seahorse::Client::Handler
7
9
 
10
+ # Useful because Aws::S3::Errors::SignatureDoesNotMatch is thrown
11
+ # when passed a bucket with a forward slash. Instead provide a more
12
+ # helpful error. Ideally should not be a plugin?
8
13
  def call(context)
9
- if context.params.key?(:bucket) && context.params[:bucket].include?('/')
10
- msg = ":bucket option must not contain a forward-slash (/)"
11
- raise ArgumentError, msg
14
+ bucket_member = _bucket_member(context.operation.input.shape)
15
+ if bucket_member && (bucket = context.params[bucket_member])
16
+ _resolved_region, arn = ARN.resolve_arn!(
17
+ bucket,
18
+ context.config.region,
19
+ context.config.s3_use_arn_region
20
+ )
21
+ if !arn && bucket.include?('/')
22
+ raise ArgumentError,
23
+ 'bucket name must not contain a forward-slash (/)'
24
+ end
12
25
  end
13
26
  @handler.call(context)
14
27
  end
15
28
 
29
+ private
30
+
31
+ def _bucket_member(input)
32
+ input.members.each do |member, ref|
33
+ return member if ref.shape.name == 'BucketName'
34
+ end
35
+ nil
36
+ end
37
+
16
38
  end
17
39
 
18
40
  handler(Handler)
@@ -1,27 +1,28 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws
2
4
  module S3
3
5
  module Plugins
4
6
  # @api private
5
7
  class Dualstack < Seahorse::Client::Plugin
6
-
7
- option(:use_dualstack_endpoint,
8
- default: false,
9
- doc_type: 'Boolean',
10
- docstring: <<-DOCS)
11
- When set to `true`, IPv6-compatible bucket endpoints will be used
12
- for all operations.
13
- DOCS
14
-
15
8
  def add_handlers(handlers, config)
16
9
  handlers.add(OptionHandler, step: :initialize)
17
- handlers.add(DualstackHandler, step: :build, priority: 0)
10
+ handlers.add(DualstackHandler, step: :build, priority: 49)
18
11
  end
19
12
 
20
13
  # @api private
21
14
  class OptionHandler < Seahorse::Client::Handler
22
15
  def call(context)
23
- dualstack = context.params.delete(:use_dualstack_endpoint)
16
+ # Support client configuration and per-operation configuration
17
+ if context.params.is_a?(Hash)
18
+ dualstack = context.params.delete(:use_dualstack_endpoint)
19
+ end
24
20
  dualstack = context.config.use_dualstack_endpoint if dualstack.nil?
21
+ # Raise if :endpoint and dualstack are both provided
22
+ if dualstack && !context.config.regional_endpoint
23
+ raise ArgumentError,
24
+ 'Cannot use both :use_dualstack_endpoint and :endpoint'
25
+ end
25
26
  context[:use_dualstack_endpoint] = dualstack
26
27
  @handler.call(context)
27
28
  end
@@ -30,37 +31,41 @@ for all operations.
30
31
  # @api private
31
32
  class DualstackHandler < Seahorse::Client::Handler
32
33
  def call(context)
33
- apply_dualstack_endpoint(context) if use_dualstack_endpoint?(context)
34
+ # only rewrite the endpoint if it's not a custom endpoint
35
+ # accelerate/ARN already handle dualstack cases, so ignore these
36
+ # check to see if dualstack is on but configured off via operation
37
+ if context.config.regional_endpoint &&
38
+ use_dualstack_endpoint?(context)
39
+ apply_dualstack_endpoint(context)
40
+ end
34
41
  @handler.call(context)
35
42
  end
36
43
 
37
44
  private
38
- def apply_dualstack_endpoint(context)
39
- bucket_name = context.params[:bucket]
40
- region = context.config.region
41
- context.config.force_path_style
42
- dns_suffix = Aws::Partitions::EndpointProvider.dns_suffix_for(region)
43
45
 
44
- if use_bucket_dns?(bucket_name, context)
45
- host = "#{bucket_name}.s3.dualstack.#{region}.#{dns_suffix}"
46
- else
47
- host = "s3.dualstack.#{region}.#{dns_suffix}"
48
- end
46
+ def apply_dualstack_endpoint(context)
47
+ new_endpoint = Aws::Partitions::EndpointProvider.resolve(
48
+ context.config.region,
49
+ 's3',
50
+ 'regional',
51
+ {
52
+ dualstack: context[:use_dualstack_endpoint],
53
+ fips: context.config.use_fips_endpoint
54
+ }
55
+ )
49
56
  endpoint = URI.parse(context.http_request.endpoint.to_s)
50
- endpoint.scheme = context.http_request.endpoint.scheme
51
- endpoint.port = context.http_request.endpoint.port
52
- endpoint.host = host
53
- context.http_request.endpoint = endpoint.to_s
54
- end
55
-
56
- def use_bucket_dns?(bucket_name, context)
57
- ssl = context.http_request.endpoint.scheme == "https"
58
- bucket_name && BucketDns.dns_compatible?(bucket_name, ssl) &&
59
- !context.config.force_path_style
57
+ endpoint.host = URI.parse(new_endpoint).host
58
+ context.http_request.endpoint = endpoint
60
59
  end
61
60
 
62
61
  def use_dualstack_endpoint?(context)
63
- context[:use_dualstack_endpoint] && !context[:use_accelerate_endpoint]
62
+ # case when dualstack is turned off via operation
63
+ (context[:use_dualstack_endpoint] ||
64
+ context.config.use_dualstack_endpoint) &&
65
+ # accelerate plugin already applies dualstack
66
+ !context[:use_accelerate_endpoint] &&
67
+ # arns handle dualstack
68
+ !context.metadata[:s3_arn]
64
69
  end
65
70
  end
66
71
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws
2
4
  module S3
3
5
  module Plugins
@@ -13,10 +15,8 @@ module Aws
13
15
  class Handler < Seahorse::Client::Handler
14
16
 
15
17
  def call(context)
16
- if
17
- context.http_request.body &&
18
- context.http_request.body.size > 0
19
- then
18
+ body = context.http_request.body
19
+ if body.respond_to?(:size) && body.size > 0
20
20
  context.http_request.headers['expect'] = '100-continue'
21
21
  end
22
22
  @handler.call(context)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws
2
4
  module S3
3
5
  module Plugins
@@ -9,7 +11,7 @@ module Aws
9
11
  @handler.call(context).on(200) do |response|
10
12
  response.data = S3::Types::GetBucketLocationOutput.new
11
13
  xml = context.http_response.body_contents
12
- matches = xml.match(/>(.+?)<\/LocationConstraint>/)
14
+ matches = xml.match(/<LocationConstraint.*?>(.+?)<\/LocationConstraint>/)
13
15
  response.data[:location_constraint] = matches ? matches[1] : ''
14
16
  end
15
17
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws
2
4
  module S3
3
5
  module Plugins
@@ -27,12 +29,19 @@ module Aws
27
29
  error_code = xml.match(/<Code>(.+?)<\/Code>/)[1]
28
30
  error_message = xml.match(/<Message>(.+?)<\/Message>/)[1]
29
31
  S3::Errors.error_class(error_code).new(context, error_message)
32
+ elsif !xml.match(/<\w/) # Must have the start of an XML Tag
33
+ # Other incomplete xml bodies will result in XML ParsingError
34
+ Seahorse::Client::NetworkingError.new(
35
+ S3::Errors
36
+ .error_class('InternalError')
37
+ .new(context, 'Empty or incomplete response body')
38
+ )
30
39
  end
31
40
  end
32
-
33
41
  end
34
42
 
35
- handler(Handler,
43
+ handler(
44
+ Handler,
36
45
  step: :sign,
37
46
  operations: [
38
47
  :complete_multipart_upload,
@@ -40,7 +49,6 @@ module Aws
40
49
  :upload_part_copy,
41
50
  ]
42
51
  )
43
-
44
52
  end
45
53
  end
46
54
  end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module S3
5
+ module Plugins
6
+
7
+ class IADRegionalEndpoint < Seahorse::Client::Plugin
8
+
9
+ option(:s3_us_east_1_regional_endpoint,
10
+ default: 'legacy',
11
+ doc_type: String,
12
+ docstring: <<-DOCS) do |cfg|
13
+ Pass in `regional` to enable the `us-east-1` regional endpoint.
14
+ Defaults to `legacy` mode which uses the global endpoint.
15
+ DOCS
16
+ resolve_iad_regional_endpoint(cfg)
17
+ end
18
+
19
+ def add_handlers(handlers, config)
20
+ # only modify non-custom endpoints
21
+ if config.regional_endpoint && config.region == 'us-east-1'
22
+ handlers.add(Handler)
23
+ end
24
+ end
25
+
26
+ # @api private
27
+ class Handler < Seahorse::Client::Handler
28
+
29
+ def call(context)
30
+ # WriteGetObjectResponse does not have a global endpoint
31
+ # ARNs are regionalized, so don't touch those either.
32
+ if context.operation.name != 'WriteGetObjectResponse' &&
33
+ context.config.s3_us_east_1_regional_endpoint == 'legacy' &&
34
+ !context.metadata[:s3_arn]
35
+ host = context.http_request.endpoint.host
36
+ legacy_host = IADRegionalEndpoint.legacy_host(host)
37
+ context.http_request.endpoint.host = legacy_host
38
+ end
39
+ @handler.call(context)
40
+ end
41
+
42
+ end
43
+
44
+ def self.legacy_host(host)
45
+ host.sub(".us-east-1", '')
46
+ end
47
+
48
+ private
49
+
50
+ def self.resolve_iad_regional_endpoint(cfg)
51
+ default_mode_value =
52
+ if cfg.respond_to?(:defaults_mode_config_resolver)
53
+ cfg.defaults_mode_config_resolver.resolve(:s3_us_east_1_regional_endpoint)
54
+ end
55
+
56
+ mode = ENV['AWS_S3_US_EAST_1_REGIONAL_ENDPOINT'] ||
57
+ Aws.shared_config.s3_us_east_1_regional_endpoint(profile: cfg.profile) ||
58
+ default_mode_value ||
59
+ 'legacy'
60
+ mode = mode.downcase
61
+ unless %w(legacy regional).include?(mode)
62
+ raise ArgumentError, "expected :s3_us_east_1_regional_endpoint or"\
63
+ " ENV['AWS_S3_US_EAST_1_REGIONAL_ENDPOINT'] to be `legacy` or"\
64
+ " `regional`."
65
+ end
66
+ mode
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+ end
73
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws
2
4
  module S3
3
5
  module Plugins