aws-sdk-s3 1.75.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/lib/aws-sdk-s3.rb +73 -0
  3. data/lib/aws-sdk-s3/bucket.rb +861 -0
  4. data/lib/aws-sdk-s3/bucket_acl.rb +277 -0
  5. data/lib/aws-sdk-s3/bucket_cors.rb +262 -0
  6. data/lib/aws-sdk-s3/bucket_lifecycle.rb +264 -0
  7. data/lib/aws-sdk-s3/bucket_lifecycle_configuration.rb +283 -0
  8. data/lib/aws-sdk-s3/bucket_logging.rb +251 -0
  9. data/lib/aws-sdk-s3/bucket_notification.rb +293 -0
  10. data/lib/aws-sdk-s3/bucket_policy.rb +242 -0
  11. data/lib/aws-sdk-s3/bucket_region_cache.rb +81 -0
  12. data/lib/aws-sdk-s3/bucket_request_payment.rb +236 -0
  13. data/lib/aws-sdk-s3/bucket_tagging.rb +251 -0
  14. data/lib/aws-sdk-s3/bucket_versioning.rb +312 -0
  15. data/lib/aws-sdk-s3/bucket_website.rb +292 -0
  16. data/lib/aws-sdk-s3/client.rb +11818 -0
  17. data/lib/aws-sdk-s3/client_api.rb +3014 -0
  18. data/lib/aws-sdk-s3/customizations.rb +34 -0
  19. data/lib/aws-sdk-s3/customizations/bucket.rb +162 -0
  20. data/lib/aws-sdk-s3/customizations/multipart_upload.rb +44 -0
  21. data/lib/aws-sdk-s3/customizations/object.rb +389 -0
  22. data/lib/aws-sdk-s3/customizations/object_summary.rb +85 -0
  23. data/lib/aws-sdk-s3/customizations/types/list_object_versions_output.rb +13 -0
  24. data/lib/aws-sdk-s3/encryption.rb +21 -0
  25. data/lib/aws-sdk-s3/encryption/client.rb +375 -0
  26. data/lib/aws-sdk-s3/encryption/decrypt_handler.rb +190 -0
  27. data/lib/aws-sdk-s3/encryption/default_cipher_provider.rb +65 -0
  28. data/lib/aws-sdk-s3/encryption/default_key_provider.rb +40 -0
  29. data/lib/aws-sdk-s3/encryption/encrypt_handler.rb +61 -0
  30. data/lib/aws-sdk-s3/encryption/errors.rb +15 -0
  31. data/lib/aws-sdk-s3/encryption/io_auth_decrypter.rb +58 -0
  32. data/lib/aws-sdk-s3/encryption/io_decrypter.rb +36 -0
  33. data/lib/aws-sdk-s3/encryption/io_encrypter.rb +71 -0
  34. data/lib/aws-sdk-s3/encryption/key_provider.rb +31 -0
  35. data/lib/aws-sdk-s3/encryption/kms_cipher_provider.rb +75 -0
  36. data/lib/aws-sdk-s3/encryption/materials.rb +60 -0
  37. data/lib/aws-sdk-s3/encryption/utils.rb +81 -0
  38. data/lib/aws-sdk-s3/encryptionV2/client.rb +388 -0
  39. data/lib/aws-sdk-s3/encryptionV2/decrypt_handler.rb +198 -0
  40. data/lib/aws-sdk-s3/encryptionV2/default_cipher_provider.rb +103 -0
  41. data/lib/aws-sdk-s3/encryptionV2/default_key_provider.rb +38 -0
  42. data/lib/aws-sdk-s3/encryptionV2/encrypt_handler.rb +66 -0
  43. data/lib/aws-sdk-s3/encryptionV2/errors.rb +13 -0
  44. data/lib/aws-sdk-s3/encryptionV2/io_auth_decrypter.rb +56 -0
  45. data/lib/aws-sdk-s3/encryptionV2/io_decrypter.rb +35 -0
  46. data/lib/aws-sdk-s3/encryptionV2/io_encrypter.rb +71 -0
  47. data/lib/aws-sdk-s3/encryptionV2/key_provider.rb +29 -0
  48. data/lib/aws-sdk-s3/encryptionV2/kms_cipher_provider.rb +99 -0
  49. data/lib/aws-sdk-s3/encryptionV2/materials.rb +58 -0
  50. data/lib/aws-sdk-s3/encryptionV2/utils.rb +116 -0
  51. data/lib/aws-sdk-s3/encryption_v2.rb +20 -0
  52. data/lib/aws-sdk-s3/errors.rb +115 -0
  53. data/lib/aws-sdk-s3/event_streams.rb +69 -0
  54. data/lib/aws-sdk-s3/file_downloader.rb +142 -0
  55. data/lib/aws-sdk-s3/file_part.rb +78 -0
  56. data/lib/aws-sdk-s3/file_uploader.rb +70 -0
  57. data/lib/aws-sdk-s3/legacy_signer.rb +189 -0
  58. data/lib/aws-sdk-s3/multipart_file_uploader.rb +227 -0
  59. data/lib/aws-sdk-s3/multipart_stream_uploader.rb +173 -0
  60. data/lib/aws-sdk-s3/multipart_upload.rb +401 -0
  61. data/lib/aws-sdk-s3/multipart_upload_error.rb +18 -0
  62. data/lib/aws-sdk-s3/multipart_upload_part.rb +423 -0
  63. data/lib/aws-sdk-s3/object.rb +1422 -0
  64. data/lib/aws-sdk-s3/object_acl.rb +333 -0
  65. data/lib/aws-sdk-s3/object_copier.rb +101 -0
  66. data/lib/aws-sdk-s3/object_multipart_copier.rb +182 -0
  67. data/lib/aws-sdk-s3/object_summary.rb +1181 -0
  68. data/lib/aws-sdk-s3/object_version.rb +550 -0
  69. data/lib/aws-sdk-s3/plugins/accelerate.rb +87 -0
  70. data/lib/aws-sdk-s3/plugins/bucket_arn.rb +212 -0
  71. data/lib/aws-sdk-s3/plugins/bucket_dns.rb +91 -0
  72. data/lib/aws-sdk-s3/plugins/bucket_name_restrictions.rb +45 -0
  73. data/lib/aws-sdk-s3/plugins/dualstack.rb +74 -0
  74. data/lib/aws-sdk-s3/plugins/expect_100_continue.rb +28 -0
  75. data/lib/aws-sdk-s3/plugins/get_bucket_location_fix.rb +25 -0
  76. data/lib/aws-sdk-s3/plugins/http_200_errors.rb +55 -0
  77. data/lib/aws-sdk-s3/plugins/iad_regional_endpoint.rb +62 -0
  78. data/lib/aws-sdk-s3/plugins/location_constraint.rb +35 -0
  79. data/lib/aws-sdk-s3/plugins/md5s.rb +84 -0
  80. data/lib/aws-sdk-s3/plugins/redirects.rb +45 -0
  81. data/lib/aws-sdk-s3/plugins/s3_host_id.rb +30 -0
  82. data/lib/aws-sdk-s3/plugins/s3_signer.rb +222 -0
  83. data/lib/aws-sdk-s3/plugins/sse_cpk.rb +70 -0
  84. data/lib/aws-sdk-s3/plugins/streaming_retry.rb +118 -0
  85. data/lib/aws-sdk-s3/plugins/url_encoded_keys.rb +97 -0
  86. data/lib/aws-sdk-s3/presigned_post.rb +686 -0
  87. data/lib/aws-sdk-s3/presigner.rb +253 -0
  88. data/lib/aws-sdk-s3/resource.rb +117 -0
  89. data/lib/aws-sdk-s3/types.rb +13154 -0
  90. data/lib/aws-sdk-s3/waiters.rb +243 -0
  91. metadata +184 -0
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module S3
5
+ module Plugins
6
+ class Expect100Continue < Seahorse::Client::Plugin
7
+
8
+ def add_handlers(handlers, config)
9
+ if config.http_continue_timeout && config.http_continue_timeout > 0
10
+ handlers.add(Handler)
11
+ end
12
+ end
13
+
14
+ # @api private
15
+ class Handler < Seahorse::Client::Handler
16
+
17
+ def call(context)
18
+ if context.http_request.body && context.http_request.body.size > 0
19
+ context.http_request.headers['expect'] = '100-continue'
20
+ end
21
+ @handler.call(context)
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module S3
5
+ module Plugins
6
+ class GetBucketLocationFix < Seahorse::Client::Plugin
7
+
8
+ class Handler < Seahorse::Client::Handler
9
+
10
+ def call(context)
11
+ @handler.call(context).on(200) do |response|
12
+ response.data = S3::Types::GetBucketLocationOutput.new
13
+ xml = context.http_response.body_contents
14
+ matches = xml.match(/>(.+?)<\/LocationConstraint>/)
15
+ response.data[:location_constraint] = matches ? matches[1] : ''
16
+ end
17
+ end
18
+ end
19
+
20
+ handler(Handler, priority: 60, operations: [:get_bucket_location])
21
+
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module S3
5
+ module Plugins
6
+
7
+ # A handful of Amazon S3 operations will respond with a 200 status
8
+ # code but will send an error in the response body. This plugin
9
+ # injects a handler that will parse 200 response bodies for potential
10
+ # errors, allowing them to be retried.
11
+ # @api private
12
+ class Http200Errors < Seahorse::Client::Plugin
13
+
14
+ class Handler < Seahorse::Client::Handler
15
+
16
+ def call(context)
17
+ @handler.call(context).on(200) do |response|
18
+ if error = check_for_error(context)
19
+ context.http_response.status_code = 500
20
+ response.data = nil
21
+ response.error = error
22
+ end
23
+ end
24
+ end
25
+
26
+ def check_for_error(context)
27
+ xml = context.http_response.body_contents
28
+ if xml.match(/<Error>/)
29
+ error_code = xml.match(/<Code>(.+?)<\/Code>/)[1]
30
+ error_message = xml.match(/<Message>(.+?)<\/Message>/)[1]
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
+ )
39
+ end
40
+ end
41
+ end
42
+
43
+ handler(
44
+ Handler,
45
+ step: :sign,
46
+ operations: [
47
+ :complete_multipart_upload,
48
+ :copy_object,
49
+ :upload_part_copy,
50
+ ]
51
+ )
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,62 @@
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
+ Passing in `regional` to enable regional endpoint for S3's `us-east-1`
14
+ region. Defaults to `legacy` mode using global endpoint.
15
+ DOCS
16
+ resolve_iad_regional_endpoint(cfg)
17
+ end
18
+
19
+ def add_handlers(handlers, config)
20
+ if config.region == 'us-east-1'
21
+ handlers.add(Handler)
22
+ end
23
+ end
24
+
25
+ # @api private
26
+ class Handler < Seahorse::Client::Handler
27
+
28
+ def call(context)
29
+ # keep legacy global endpoint pattern by default
30
+ if context.config.s3_us_east_1_regional_endpoint == 'legacy'
31
+ context.http_request.endpoint.host = IADRegionalEndpoint.legacy_host(
32
+ context.http_request.endpoint.host)
33
+ end
34
+ @handler.call(context)
35
+ end
36
+
37
+ end
38
+
39
+ def self.legacy_host(host)
40
+ host.sub(".us-east-1", '')
41
+ end
42
+
43
+ private
44
+
45
+ def self.resolve_iad_regional_endpoint(cfg)
46
+ mode = ENV['AWS_S3_US_EAST_1_REGIONAL_ENDPOINT'] ||
47
+ Aws.shared_config.s3_us_east_1_regional_endpoint(profile: cfg.profile) ||
48
+ 'legacy'
49
+ mode = mode.downcase
50
+ unless %w(legacy regional).include?(mode)
51
+ raise ArgumentError, "expected :s3_us_east_1_regional_endpoint or"\
52
+ " ENV['AWS_S3_US_EAST_1_REGIONAL_ENDPOINT'] to be `legacy` or"\
53
+ " `regional`."
54
+ end
55
+ mode
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module S3
5
+ module Plugins
6
+
7
+ # When making calls to {S3::Client#create_bucket} outside the
8
+ # "classic" region, the bucket location constraint must be specified.
9
+ # This plugin auto populates the constraint to the configured region.
10
+ class LocationConstraint < Seahorse::Client::Plugin
11
+
12
+ class Handler < Seahorse::Client::Handler
13
+
14
+ def call(context)
15
+ unless context.config.region == 'us-east-1'
16
+ populate_location_constraint(context.params, context.config.region)
17
+ end
18
+ @handler.call(context)
19
+ end
20
+
21
+ private
22
+
23
+ def populate_location_constraint(params, region)
24
+ params[:create_bucket_configuration] ||= {}
25
+ params[:create_bucket_configuration][:location_constraint] ||= region
26
+ end
27
+
28
+ end
29
+
30
+ handler(Handler, step: :initialize, operations: [:create_bucket])
31
+
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openssl'
4
+
5
+ module Aws
6
+ module S3
7
+ module Plugins
8
+ # @api private
9
+ # This plugin is effectively deprecated in favor of modeled
10
+ # httpChecksumRequired traits.
11
+ class Md5s < Seahorse::Client::Plugin
12
+ # These operations allow Content MD5 but are not required by
13
+ # httpChecksumRequired. This list should not grow.
14
+ OPTIONAL_OPERATIONS = [
15
+ :put_object,
16
+ :upload_part
17
+ ]
18
+
19
+ # @api private
20
+ class Handler < Seahorse::Client::Handler
21
+
22
+ CHUNK_SIZE = 1 * 1024 * 1024 # one MB
23
+
24
+ def call(context)
25
+ body = context.http_request.body
26
+ if body.size > 0
27
+ context.http_request.headers['Content-Md5'] ||= md5(body)
28
+ end
29
+ @handler.call(context)
30
+ end
31
+
32
+ private
33
+
34
+ # @param [File, Tempfile, IO#read, String] value
35
+ # @return [String<MD5>]
36
+ def md5(value)
37
+ if (File === value || Tempfile === value) && !value.path.nil? && File.exist?(value.path)
38
+ OpenSSL::Digest::MD5.file(value).base64digest
39
+ elsif value.respond_to?(:read)
40
+ md5 = OpenSSL::Digest::MD5.new
41
+ update_in_chunks(md5, value)
42
+ md5.base64digest
43
+ else
44
+ OpenSSL::Digest::MD5.digest(value).base64digest
45
+ end
46
+ end
47
+
48
+ def update_in_chunks(digest, io)
49
+ loop do
50
+ chunk = io.read(CHUNK_SIZE)
51
+ break unless chunk
52
+ digest.update(chunk)
53
+ end
54
+ io.rewind
55
+ end
56
+
57
+ end
58
+
59
+ option(:compute_checksums,
60
+ default: true,
61
+ doc_type: 'Boolean',
62
+ docstring: <<-DOCS)
63
+ When `true` a MD5 checksum will be computed and sent in the Content Md5
64
+ header for :put_object and :upload_part. When `false`, MD5 checksums
65
+ will not be computed for these operations. Checksums are still computed
66
+ for operations requiring them. Checksum errors returned by Amazon S3 are
67
+ automatically retried up to `:retry_limit` times.
68
+ DOCS
69
+
70
+ def add_handlers(handlers, config)
71
+ if config.compute_checksums
72
+ # priority set low to ensure md5 is computed AFTER the request is
73
+ # built but before it is signed
74
+ handlers.add(
75
+ Handler,
76
+ priority: 10, step: :build, operations: OPTIONAL_OPERATIONS
77
+ )
78
+ end
79
+ end
80
+
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module S3
5
+ module Plugins
6
+ class Redirects < Seahorse::Client::Plugin
7
+
8
+ option(:follow_redirects,
9
+ default: true,
10
+ doc_type: 'Boolean',
11
+ docstring: <<-DOCS)
12
+ When `true`, this client will follow 307 redirects returned
13
+ by Amazon S3.
14
+ DOCS
15
+
16
+ # @api private
17
+ class Handler < Seahorse::Client::Handler
18
+
19
+ def call(context)
20
+ response = @handler.call(context)
21
+ if context.http_response.status_code == 307
22
+ endpoint = context.http_response.headers['location']
23
+ unless context.http_request.endpoint.host.include?('fips')
24
+ context.http_request.endpoint = endpoint
25
+ end
26
+ context.http_response.body.truncate(0)
27
+ @handler.call(context)
28
+ else
29
+ response
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ def add_handlers(handlers, config)
36
+ if config.follow_redirects
37
+ # we want to re-trigger request signing
38
+ handlers.add(Handler, step: :sign, priority: 90)
39
+ end
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module S3
5
+ module Plugins
6
+
7
+ # Support S3 host id, more information, see:
8
+ # http://docs.aws.amazon.com/AmazonS3/latest/dev/troubleshooting.html#sdk-request-ids
9
+ #
10
+ # This plugin adds :host_id for s3 responses when available
11
+ # @api private
12
+ class S3HostId < Seahorse::Client::Plugin
13
+
14
+ class Handler < Seahorse::Client::Handler
15
+
16
+ def call(context)
17
+ response = @handler.call(context)
18
+ h = context.http_response.headers
19
+ context[:s3_host_id] = h['x-amz-id-2']
20
+ response
21
+ end
22
+
23
+ end
24
+
25
+ handler(Handler, step: :sign)
26
+
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,222 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'aws-sigv4'
4
+
5
+ module Aws
6
+ module S3
7
+ module Plugins
8
+ # This plugin is an implementation detail and may be modified.
9
+ # @api private
10
+ class S3Signer < Seahorse::Client::Plugin
11
+ option(:signature_version, 'v4')
12
+
13
+ option(:sigv4_signer) do |cfg|
14
+ S3Signer.build_v4_signer(
15
+ region: cfg.sigv4_region,
16
+ credentials: cfg.credentials
17
+ )
18
+ end
19
+
20
+ option(:sigv4_region) do |cfg|
21
+ raise Aws::Errors::MissingRegionError if cfg.region.nil?
22
+
23
+ Aws::Partitions::EndpointProvider.signing_region(cfg.region, 's3')
24
+ end
25
+
26
+ def add_handlers(handlers, cfg)
27
+ case cfg.signature_version
28
+ when 'v4' then add_v4_handlers(handlers)
29
+ when 's3' then add_legacy_handler(handlers)
30
+ else
31
+ msg = "unsupported signature version `#{cfg.signature_version}'"
32
+ raise ArgumentError, msg
33
+ end
34
+ end
35
+
36
+ def add_v4_handlers(handlers)
37
+ handlers.add(CachedBucketRegionHandler, step: :sign, priority: 60)
38
+ handlers.add(V4Handler, step: :sign)
39
+ handlers.add(BucketRegionErrorHandler, step: :sign, priority: 40)
40
+ end
41
+
42
+ def add_legacy_handler(handlers)
43
+ handlers.add(LegacyHandler, step: :sign)
44
+ end
45
+
46
+ class LegacyHandler < Seahorse::Client::Handler
47
+ def call(context)
48
+ LegacySigner.sign(context)
49
+ @handler.call(context)
50
+ end
51
+ end
52
+
53
+ class V4Handler < Seahorse::Client::Handler
54
+ def call(context)
55
+ Aws::Plugins::SignatureV4.apply_signature(
56
+ context: context,
57
+ signer: sigv4_signer(context)
58
+ )
59
+ @handler.call(context)
60
+ end
61
+
62
+ private
63
+
64
+ def sigv4_signer(context)
65
+ # If the client was configured with the wrong region,
66
+ # we have to build a new signer.
67
+ if context[:cached_sigv4_region] &&
68
+ context[:cached_sigv4_region] != context.config.sigv4_signer.region
69
+ S3Signer.build_v4_signer(
70
+ region: context[:cached_sigv4_region],
71
+ credentials: context.config.credentials
72
+ )
73
+ else
74
+ context.config.sigv4_signer
75
+ end
76
+ end
77
+ end
78
+
79
+ # This handler will update the http endpoint when the bucket region
80
+ # is known/cached.
81
+ class CachedBucketRegionHandler < Seahorse::Client::Handler
82
+ def call(context)
83
+ bucket = context.params[:bucket]
84
+ check_for_cached_region(context, bucket) if bucket
85
+ @handler.call(context)
86
+ end
87
+
88
+ private
89
+
90
+ def check_for_cached_region(context, bucket)
91
+ cached_region = S3::BUCKET_REGIONS[bucket]
92
+ if cached_region && cached_region != context.config.region
93
+ context.http_request.endpoint.host = S3Signer.new_hostname(context, cached_region)
94
+ context[:cached_sigv4_region] = cached_region
95
+ end
96
+ end
97
+ end
98
+
99
+ # This handler detects when a request fails because of a mismatched bucket
100
+ # region. It follows up by making a request to determine the correct
101
+ # region, then finally a version 4 signed request against the correct
102
+ # regional endpoint.
103
+ class BucketRegionErrorHandler < Seahorse::Client::Handler
104
+ def call(context)
105
+ response = @handler.call(context)
106
+ handle_region_errors(response)
107
+ end
108
+
109
+ private
110
+
111
+ def handle_region_errors(response)
112
+ if wrong_sigv4_region?(response) &&
113
+ !fips_region?(response) &&
114
+ !custom_endpoint?(response)
115
+ get_region_and_retry(response.context)
116
+ else
117
+ response
118
+ end
119
+ end
120
+
121
+ def get_region_and_retry(context)
122
+ actual_region = context.http_response.headers['x-amz-bucket-region']
123
+ actual_region ||= region_from_body(context.http_response.body_contents)
124
+ update_bucket_cache(context, actual_region)
125
+ log_warning(context, actual_region)
126
+ resign_with_new_region(context, actual_region)
127
+ @handler.call(context)
128
+ end
129
+
130
+ def update_bucket_cache(context, actual_region)
131
+ S3::BUCKET_REGIONS[context.params[:bucket]] = actual_region
132
+ end
133
+
134
+ def fips_region?(resp)
135
+ resp.context.http_request.endpoint.host.include?('fips')
136
+ end
137
+
138
+ def custom_endpoint?(resp)
139
+ resolved_suffix = Aws::Partitions::EndpointProvider.dns_suffix_for(
140
+ resp.context.config.region
141
+ )
142
+ !resp.context.http_request.endpoint.hostname.include?(resolved_suffix)
143
+ end
144
+
145
+ def wrong_sigv4_region?(resp)
146
+ resp.context.http_response.status_code == 400 &&
147
+ (resp.context.http_response.headers['x-amz-bucket-region'] ||
148
+ resp.context.http_response.body_contents.match(/<Region>.+?<\/Region>/))
149
+ end
150
+
151
+ def resign_with_new_region(context, actual_region)
152
+ context.http_response.body.truncate(0)
153
+ context.http_request.endpoint.host = S3Signer.new_hostname(context, actual_region)
154
+ context.metadata[:redirect_region] = actual_region
155
+ Aws::Plugins::SignatureV4.apply_signature(
156
+ context: context,
157
+ signer: S3Signer.build_v4_signer(
158
+ region: actual_region,
159
+ credentials: context.config.credentials
160
+ )
161
+ )
162
+ end
163
+
164
+ def region_from_body(body)
165
+ region = body.match(/<Region>(.+?)<\/Region>/)[1]
166
+ if region.nil? || region == ''
167
+ raise "couldn't get region from body: #{body}"
168
+ else
169
+ region
170
+ end
171
+ end
172
+
173
+ def log_warning(context, actual_region)
174
+ msg = "S3 client configured for #{context.config.region.inspect} " \
175
+ "but the bucket #{context.params[:bucket].inspect} is in " \
176
+ "#{actual_region.inspect}; Please configure the proper region " \
177
+ "to avoid multiple unnecessary redirects and signing attempts\n"
178
+ if (logger = context.config.logger)
179
+ logger.warn(msg)
180
+ else
181
+ warn(msg)
182
+ end
183
+ end
184
+ end
185
+
186
+ class << self
187
+ # @option options [required, String] :region
188
+ # @option options [required, #credentials] :credentials
189
+ # @api private
190
+ def build_v4_signer(options = {})
191
+ Aws::Sigv4::Signer.new(
192
+ service: 's3',
193
+ region: options[:region],
194
+ credentials_provider: options[:credentials],
195
+ uri_escape_path: false,
196
+ unsigned_headers: ['content-length', 'x-amzn-trace-id']
197
+ )
198
+ end
199
+
200
+ def new_hostname(context, region)
201
+ # Check to see if the bucket is actually an ARN and resolve it
202
+ # Otherwise it will retry with the ARN as the bucket name.
203
+ resolved_bucket, resolved_region, arn = BucketARN.resolve_arn!(
204
+ context.params[:bucket],
205
+ region,
206
+ context.config.s3_use_arn_region
207
+ )
208
+ uri = URI.parse(
209
+ Aws::Partitions::EndpointProvider.resolve(resolved_region, 's3')
210
+ )
211
+
212
+ if arn
213
+ BucketARN.resolve_url!(uri, arn).host
214
+ else
215
+ resolved_bucket + '.' + uri.host
216
+ end
217
+ end
218
+ end
219
+ end
220
+ end
221
+ end
222
+ end