aws-sdk-s3 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/lib/aws-sdk-s3.rb +66 -0
  3. data/lib/aws-sdk-s3/bucket.rb +595 -0
  4. data/lib/aws-sdk-s3/bucket_acl.rb +168 -0
  5. data/lib/aws-sdk-s3/bucket_cors.rb +146 -0
  6. data/lib/aws-sdk-s3/bucket_lifecycle.rb +164 -0
  7. data/lib/aws-sdk-s3/bucket_logging.rb +142 -0
  8. data/lib/aws-sdk-s3/bucket_notification.rb +187 -0
  9. data/lib/aws-sdk-s3/bucket_policy.rb +138 -0
  10. data/lib/aws-sdk-s3/bucket_region_cache.rb +79 -0
  11. data/lib/aws-sdk-s3/bucket_request_payment.rb +128 -0
  12. data/lib/aws-sdk-s3/bucket_tagging.rb +143 -0
  13. data/lib/aws-sdk-s3/bucket_versioning.rb +188 -0
  14. data/lib/aws-sdk-s3/bucket_website.rb +177 -0
  15. data/lib/aws-sdk-s3/client.rb +3171 -0
  16. data/lib/aws-sdk-s3/client_api.rb +1991 -0
  17. data/lib/aws-sdk-s3/customizations.rb +29 -0
  18. data/lib/aws-sdk-s3/customizations/bucket.rb +127 -0
  19. data/lib/aws-sdk-s3/customizations/multipart_upload.rb +42 -0
  20. data/lib/aws-sdk-s3/customizations/object.rb +257 -0
  21. data/lib/aws-sdk-s3/customizations/object_summary.rb +65 -0
  22. data/lib/aws-sdk-s3/customizations/types/list_object_versions_output.rb +11 -0
  23. data/lib/aws-sdk-s3/encryption.rb +19 -0
  24. data/lib/aws-sdk-s3/encryption/client.rb +369 -0
  25. data/lib/aws-sdk-s3/encryption/decrypt_handler.rb +178 -0
  26. data/lib/aws-sdk-s3/encryption/default_cipher_provider.rb +63 -0
  27. data/lib/aws-sdk-s3/encryption/default_key_provider.rb +38 -0
  28. data/lib/aws-sdk-s3/encryption/encrypt_handler.rb +50 -0
  29. data/lib/aws-sdk-s3/encryption/errors.rb +13 -0
  30. data/lib/aws-sdk-s3/encryption/io_auth_decrypter.rb +50 -0
  31. data/lib/aws-sdk-s3/encryption/io_decrypter.rb +29 -0
  32. data/lib/aws-sdk-s3/encryption/io_encrypter.rb +69 -0
  33. data/lib/aws-sdk-s3/encryption/key_provider.rb +29 -0
  34. data/lib/aws-sdk-s3/encryption/kms_cipher_provider.rb +71 -0
  35. data/lib/aws-sdk-s3/encryption/materials.rb +58 -0
  36. data/lib/aws-sdk-s3/encryption/utils.rb +79 -0
  37. data/lib/aws-sdk-s3/errors.rb +23 -0
  38. data/lib/aws-sdk-s3/file_part.rb +75 -0
  39. data/lib/aws-sdk-s3/file_uploader.rb +58 -0
  40. data/lib/aws-sdk-s3/legacy_signer.rb +186 -0
  41. data/lib/aws-sdk-s3/multipart_file_uploader.rb +187 -0
  42. data/lib/aws-sdk-s3/multipart_upload.rb +287 -0
  43. data/lib/aws-sdk-s3/multipart_upload_error.rb +16 -0
  44. data/lib/aws-sdk-s3/multipart_upload_part.rb +314 -0
  45. data/lib/aws-sdk-s3/object.rb +942 -0
  46. data/lib/aws-sdk-s3/object_acl.rb +214 -0
  47. data/lib/aws-sdk-s3/object_copier.rb +99 -0
  48. data/lib/aws-sdk-s3/object_multipart_copier.rb +179 -0
  49. data/lib/aws-sdk-s3/object_summary.rb +794 -0
  50. data/lib/aws-sdk-s3/object_version.rb +406 -0
  51. data/lib/aws-sdk-s3/plugins/accelerate.rb +92 -0
  52. data/lib/aws-sdk-s3/plugins/bucket_dns.rb +89 -0
  53. data/lib/aws-sdk-s3/plugins/bucket_name_restrictions.rb +23 -0
  54. data/lib/aws-sdk-s3/plugins/dualstack.rb +70 -0
  55. data/lib/aws-sdk-s3/plugins/expect_100_continue.rb +29 -0
  56. data/lib/aws-sdk-s3/plugins/get_bucket_location_fix.rb +23 -0
  57. data/lib/aws-sdk-s3/plugins/http_200_errors.rb +47 -0
  58. data/lib/aws-sdk-s3/plugins/location_constraint.rb +33 -0
  59. data/lib/aws-sdk-s3/plugins/md5s.rb +79 -0
  60. data/lib/aws-sdk-s3/plugins/redirects.rb +41 -0
  61. data/lib/aws-sdk-s3/plugins/s3_signer.rb +208 -0
  62. data/lib/aws-sdk-s3/plugins/sse_cpk.rb +68 -0
  63. data/lib/aws-sdk-s3/plugins/url_encoded_keys.rb +94 -0
  64. data/lib/aws-sdk-s3/presigned_post.rb +647 -0
  65. data/lib/aws-sdk-s3/presigner.rb +160 -0
  66. data/lib/aws-sdk-s3/resource.rb +96 -0
  67. data/lib/aws-sdk-s3/types.rb +5750 -0
  68. data/lib/aws-sdk-s3/waiters.rb +178 -0
  69. metadata +154 -0
@@ -0,0 +1,89 @@
1
+ module Aws
2
+ module S3
3
+ module Plugins
4
+
5
+ # Amazon S3 requires DNS style addressing for buckets outside of
6
+ # the classic region when possible.
7
+ class BucketDns < Seahorse::Client::Plugin
8
+
9
+ # When set to `false` DNS compatible bucket names are moved from
10
+ # the request URI path to the host as a subdomain, unless the request
11
+ # is using SSL and the bucket name contains a dot.
12
+ #
13
+ # When set to `true`, the bucket name is always forced to be part
14
+ # of the request URI path. This will not work with buckets outside
15
+ # the classic region.
16
+ option(:force_path_style,
17
+ default: false,
18
+ doc_type: 'Boolean',
19
+ docstring: <<-DOCS)
20
+ When set to `true`, the bucket name is always left in the
21
+ request URI and never moved to the host as a sub-domain.
22
+ DOCS
23
+
24
+ def add_handlers(handlers, config)
25
+ handlers.add(Handler) unless config.force_path_style
26
+ end
27
+
28
+ # @api private
29
+ class Handler < Seahorse::Client::Handler
30
+
31
+ def call(context)
32
+ move_dns_compat_bucket_to_subdomain(context)
33
+ @handler.call(context)
34
+ end
35
+
36
+ private
37
+
38
+ def move_dns_compat_bucket_to_subdomain(context)
39
+ bucket_name = context.params[:bucket]
40
+ endpoint = context.http_request.endpoint
41
+ if
42
+ bucket_name &&
43
+ BucketDns.dns_compatible?(bucket_name, https?(endpoint)) &&
44
+ context.operation_name != 'get_bucket_location'
45
+ then
46
+ move_bucket_to_subdomain(bucket_name, endpoint)
47
+ end
48
+ end
49
+
50
+ def move_bucket_to_subdomain(bucket_name, endpoint)
51
+ endpoint.host = "#{bucket_name}.#{endpoint.host}"
52
+ path = endpoint.path.sub("/#{bucket_name}", '')
53
+ path = "/#{path}" unless path.match(/^\//)
54
+ endpoint.path = path
55
+ end
56
+
57
+ def https?(uri)
58
+ uri.scheme == 'https'
59
+ end
60
+
61
+ end
62
+
63
+ class << self
64
+
65
+ # @param [String] bucket_name
66
+ # @param [Boolean] ssl
67
+ # @return [Boolean]
68
+ def dns_compatible?(bucket_name, ssl)
69
+ if valid_subdomain?(bucket_name)
70
+ bucket_name.match(/\./) && ssl ? false : true
71
+ else
72
+ false
73
+ end
74
+ end
75
+
76
+ private
77
+
78
+ def valid_subdomain?(bucket_name)
79
+ bucket_name.size < 64 &&
80
+ bucket_name =~ /^[a-z0-9][a-z0-9.-]+[a-z0-9]$/ &&
81
+ bucket_name !~ /(\d+\.){3}\d+/ &&
82
+ bucket_name !~ /[.-]{2}/
83
+ end
84
+
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,23 @@
1
+ module Aws
2
+ module S3
3
+ module Plugins
4
+ # @api private
5
+ class BucketNameRestrictions < Seahorse::Client::Plugin
6
+ class Handler < Seahorse::Client::Handler
7
+
8
+ 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
12
+ end
13
+ @handler.call(context)
14
+ end
15
+
16
+ end
17
+
18
+ handler(Handler)
19
+
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,70 @@
1
+ module Aws
2
+ module S3
3
+ module Plugins
4
+ # @api private
5
+ 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
+ def add_handlers(handlers, config)
16
+ handlers.add(OptionHandler, step: :initialize)
17
+ handlers.add(DualstackHandler, step: :build, priority: 0)
18
+ end
19
+
20
+ # @api private
21
+ class OptionHandler < Seahorse::Client::Handler
22
+ def call(context)
23
+ dualstack = context.params.delete(:use_dualstack_endpoint)
24
+ dualstack = context.config.use_dualstack_endpoint if dualstack.nil?
25
+ context[:use_dualstack_endpoint] = dualstack
26
+ @handler.call(context)
27
+ end
28
+ end
29
+
30
+ # @api private
31
+ class DualstackHandler < Seahorse::Client::Handler
32
+ def call(context)
33
+ apply_dualstack_endpoint(context) if use_dualstack_endpoint?(context)
34
+ @handler.call(context)
35
+ end
36
+
37
+ private
38
+ def apply_dualstack_endpoint(context)
39
+ bucket_name = context.params[:bucket]
40
+ region = context.config.region
41
+ force_path_style = context.config.force_path_style
42
+ dns_suffix = Aws::Partitions::EndpointProvider.dns_suffix_for(region)
43
+
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
49
+ 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
60
+ end
61
+
62
+ def use_dualstack_endpoint?(context)
63
+ context[:use_dualstack_endpoint] && !context[:use_accelerate_endpoint]
64
+ end
65
+ end
66
+
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,29 @@
1
+ module Aws
2
+ module S3
3
+ module Plugins
4
+ class Expect100Continue < Seahorse::Client::Plugin
5
+
6
+ def add_handlers(handlers, config)
7
+ if config.http_continue_timeout && config.http_continue_timeout > 0
8
+ handlers.add(Handler)
9
+ end
10
+ end
11
+
12
+ # @api private
13
+ class Handler < Seahorse::Client::Handler
14
+
15
+ def call(context)
16
+ if
17
+ context.http_request.body &&
18
+ context.http_request.body.size > 0
19
+ then
20
+ context.http_request.headers['expect'] = '100-continue'
21
+ end
22
+ @handler.call(context)
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,23 @@
1
+ module Aws
2
+ module S3
3
+ module Plugins
4
+ class GetBucketLocationFix < Seahorse::Client::Plugin
5
+
6
+ class Handler < Seahorse::Client::Handler
7
+
8
+ def call(context)
9
+ @handler.call(context).on(200) do |response|
10
+ response.data = S3::Types::GetBucketLocationOutput.new
11
+ xml = context.http_response.body_contents
12
+ matches = xml.match(/>(.+?)<\/LocationConstraint>/)
13
+ response.data[:location_constraint] = matches ? matches[1] : ''
14
+ end
15
+ end
16
+ end
17
+
18
+ handler(Handler, priority: 60, operations: [:get_bucket_location])
19
+
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,47 @@
1
+ module Aws
2
+ module S3
3
+ module Plugins
4
+
5
+ # A handful of Amazon S3 operations will respond with a 200 status
6
+ # code but will send an error in the response body. This plugin
7
+ # injects a handler that will parse 200 response bodies for potential
8
+ # errors, allowing them to be retried.
9
+ # @api private
10
+ class Http200Errors < Seahorse::Client::Plugin
11
+
12
+ class Handler < Seahorse::Client::Handler
13
+
14
+ def call(context)
15
+ @handler.call(context).on(200) do |response|
16
+ if error = check_for_error(context)
17
+ context.http_response.status_code = 500
18
+ response.data = nil
19
+ response.error = error
20
+ end
21
+ end
22
+ end
23
+
24
+ def check_for_error(context)
25
+ xml = context.http_response.body_contents
26
+ if xml.match(/<Error>/)
27
+ error_code = xml.match(/<Code>(.+?)<\/Code>/)[1]
28
+ error_message = xml.match(/<Message>(.+?)<\/Message>/)[1]
29
+ S3::Errors.error_class(error_code).new(context, error_message)
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ handler(Handler,
36
+ step: :sign,
37
+ operations: [
38
+ :complete_multipart_upload,
39
+ :copy_object,
40
+ :upload_part_copy,
41
+ ]
42
+ )
43
+
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,33 @@
1
+ module Aws
2
+ module S3
3
+ module Plugins
4
+
5
+ # When making calls to {S3::Client#create_bucket} outside the
6
+ # "classic" region, the bucket location constraint must be specified.
7
+ # This plugin auto populates the constraint to the configured region.
8
+ class LocationConstraint < Seahorse::Client::Plugin
9
+
10
+ class Handler < Seahorse::Client::Handler
11
+
12
+ def call(context)
13
+ unless context.config.region == 'us-east-1'
14
+ populate_location_constraint(context.params, context.config.region)
15
+ end
16
+ @handler.call(context)
17
+ end
18
+
19
+ private
20
+
21
+ def populate_location_constraint(params, region)
22
+ params[:create_bucket_configuration] ||= {}
23
+ params[:create_bucket_configuration][:location_constraint] ||= region
24
+ end
25
+
26
+ end
27
+
28
+ handler(Handler, step: :initialize, operations: [:create_bucket])
29
+
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,79 @@
1
+ require 'openssl'
2
+ require 'base64'
3
+
4
+ module Aws
5
+ module S3
6
+ module Plugins
7
+ class Md5s < Seahorse::Client::Plugin
8
+
9
+ # Amazon S3 requires these operations to have an MD5 checksum
10
+ REQUIRED_OPERATIONS = [
11
+ :delete_objects,
12
+ :put_bucket_cors,
13
+ :put_bucket_lifecycle,
14
+ :put_bucket_policy,
15
+ :put_bucket_tagging,
16
+ ]
17
+
18
+ # @api private
19
+ class Handler < Seahorse::Client::Handler
20
+
21
+ CHUNK_SIZE = 1 * 1024 * 1024 # one MB
22
+
23
+ def call(context)
24
+ body = context.http_request.body
25
+ if body.size > 0
26
+ context.http_request.headers['Content-Md5'] ||= md5(body)
27
+ end
28
+ @handler.call(context)
29
+ end
30
+
31
+ private
32
+
33
+ # @param [File, Tempfile, IO#read, String] value
34
+ # @return [String<MD5>]
35
+ def md5(value)
36
+ if (File === value || Tempfile === value) && !value.path.nil? && File.exist?(value.path)
37
+ Base64.encode64(OpenSSL::Digest::MD5.file(value).digest).strip
38
+ elsif value.respond_to?(:read)
39
+ md5 = OpenSSL::Digest::MD5.new
40
+ update_in_chunks(md5, value)
41
+ Base64.encode64(md5.digest).strip
42
+ else
43
+ Base64.encode64(OpenSSL::Digest::MD5.digest(value)).strip
44
+ end
45
+ end
46
+
47
+ def update_in_chunks(digest, io)
48
+ while chunk = io.read(CHUNK_SIZE)
49
+ digest.update(chunk)
50
+ end
51
+ io.rewind
52
+ end
53
+
54
+ end
55
+
56
+ option(:compute_checksums,
57
+ default: true,
58
+ doc_type: 'Boolean',
59
+ docstring: <<-DOCS)
60
+ When `true` a MD5 checksum will be computed for every request that
61
+ sends a body. When `false`, MD5 checksums will only be computed
62
+ for operations that require them. Checksum errors returned by Amazon
63
+ S3 are automatically retried up to `:retry_limit` times.
64
+ DOCS
65
+
66
+ def add_handlers(handlers, config)
67
+ # priority set low to ensure md5 is computed AFTER the request is
68
+ # built but before it is signed
69
+ handlers.add(Handler, {
70
+ priority: 10,
71
+ step: :build,
72
+ operations: config.compute_checksums ? nil : REQUIRED_OPERATIONS,
73
+ })
74
+ end
75
+
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,41 @@
1
+ module Aws
2
+ module S3
3
+ module Plugins
4
+ class Redirects < Seahorse::Client::Plugin
5
+
6
+ option(:follow_redirects,
7
+ default: true,
8
+ doc_type: 'Boolean',
9
+ docstring: <<-DOCS)
10
+ When `true`, this client will follow 307 redirects returned
11
+ by Amazon S3.
12
+ DOCS
13
+
14
+ # @api private
15
+ class Handler < Seahorse::Client::Handler
16
+
17
+ def call(context)
18
+ response = @handler.call(context)
19
+ if context.http_response.status_code == 307
20
+ endpoint = context.http_response.headers['location']
21
+ context.http_request.endpoint = endpoint
22
+ context.http_response.body.truncate(0)
23
+ @handler.call(context)
24
+ else
25
+ response
26
+ end
27
+ end
28
+
29
+ end
30
+
31
+ def add_handlers(handlers, config)
32
+ if config.follow_redirects
33
+ # we want to re-trigger request signing
34
+ handlers.add(Handler, step: :sign, priority: 90)
35
+ end
36
+ end
37
+
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,208 @@
1
+ require 'aws-sigv4'
2
+
3
+ module Aws
4
+ module S3
5
+ module Plugins
6
+ # This plugin is an implementation detail and may be modified.
7
+ # @api private
8
+ class S3Signer < Seahorse::Client::Plugin
9
+
10
+ option(:signature_version, 'v4')
11
+
12
+ option(:sigv4_signer) do |cfg|
13
+ S3Signer.build_v4_signer(
14
+ region: cfg.sigv4_region,
15
+ credentials: cfg.credentials
16
+ )
17
+ end
18
+
19
+ option(:sigv4_region) do |cfg|
20
+ Aws::Partitions::EndpointProvider.signing_region(cfg.region, 's3')
21
+ end
22
+
23
+ def add_handlers(handlers, cfg)
24
+ case cfg.signature_version
25
+ when 'v4' then add_v4_handlers(handlers)
26
+ when 's3' then add_legacy_handler(handlers)
27
+ else
28
+ msg = "unsupported signature version `#{cfg.signature_version}'"
29
+ raise ArgumentError, msg
30
+ end
31
+ end
32
+
33
+ def add_v4_handlers(handlers)
34
+ handlers.add(CachedBucketRegionHandler, step: :sign, priority: 60)
35
+ handlers.add(V4Handler, step: :sign)
36
+ handlers.add(BucketRegionErrorHandler, step: :sign, priority: 40)
37
+ end
38
+
39
+ def add_legacy_handler(handlers)
40
+ handlers.add(LegacyHandler, step: :sign)
41
+ end
42
+
43
+ class LegacyHandler < Seahorse::Client::Handler
44
+ def call(context)
45
+ LegacySigner.sign(context)
46
+ @handler.call(context)
47
+ end
48
+ end
49
+
50
+ class V4Handler < Seahorse::Client::Handler
51
+
52
+ def call(context)
53
+ Aws::Plugins::SignatureV4.apply_signature(
54
+ context: context,
55
+ signer: sigv4_signer(context)
56
+ )
57
+ @handler.call(context)
58
+ end
59
+
60
+ private
61
+
62
+ def sigv4_signer(context)
63
+ # If the client was configured with the wrong region,
64
+ # we have to build a new signer.
65
+ if
66
+ context[:cached_sigv4_region] &&
67
+ context[:cached_sigv4_region] != context.config.sigv4_signer.region
68
+ then
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
+
78
+ end
79
+
80
+ # This handler will update the http endpoint when the bucket region
81
+ # is known/cached.
82
+ class CachedBucketRegionHandler < Seahorse::Client::Handler
83
+
84
+ def call(context)
85
+ bucket = context.params[:bucket]
86
+ check_for_cached_region(context, bucket) if bucket
87
+ @handler.call(context)
88
+ end
89
+
90
+ private
91
+
92
+ def check_for_cached_region(context, bucket)
93
+ cached_region = S3::BUCKET_REGIONS[bucket]
94
+ if cached_region && cached_region != context.config.region
95
+ context.http_request.endpoint.host = S3Signer.new_hostname(context, cached_region)
96
+ context[:cached_sigv4_region] = cached_region
97
+ end
98
+ end
99
+
100
+ end
101
+
102
+ # This handler detects when a request fails because of a mismatched bucket
103
+ # region. It follows up by making a request to determine the correct
104
+ # region, then finally a version 4 signed request against the correct
105
+ # regional endpoint.
106
+ class BucketRegionErrorHandler < Seahorse::Client::Handler
107
+
108
+ def call(context)
109
+ response = @handler.call(context)
110
+ handle_region_errors(response)
111
+ end
112
+
113
+ private
114
+
115
+ def handle_region_errors(response)
116
+ if wrong_sigv4_region?(response)
117
+ get_region_and_retry(response.context)
118
+ else
119
+ response
120
+ end
121
+ end
122
+
123
+ def get_region_and_retry(context)
124
+ actual_region = context.http_response.headers['x-amz-bucket-region']
125
+ actual_region ||= region_from_body(context.http_response.body_contents)
126
+ update_bucket_cache(context, actual_region)
127
+ log_warning(context, actual_region)
128
+ resign_with_new_region(context, actual_region)
129
+ @handler.call(context)
130
+ end
131
+
132
+ def update_bucket_cache(context, actual_region)
133
+ S3::BUCKET_REGIONS[context.params[:bucket]] = actual_region
134
+ end
135
+
136
+ def wrong_sigv4_region?(resp)
137
+ resp.context.http_response.status_code == 400 &&
138
+ (
139
+ resp.context.http_response.headers['x-amz-bucket-region'] ||
140
+ resp.context.http_response.body_contents.match(/<Region>.+?<\/Region>/)
141
+ )
142
+ end
143
+
144
+ def resign_with_new_region(context, actual_region)
145
+ context.http_response.body.truncate(0)
146
+ context.http_request.endpoint.host = S3Signer.new_hostname(context, actual_region)
147
+ Aws::Plugins::SignatureV4.apply_signature(
148
+ context: context,
149
+ signer: S3Signer.build_v4_signer(
150
+ region: actual_region,
151
+ credentials: context.config.credentials
152
+ )
153
+ )
154
+ end
155
+
156
+ def region_from_body(body)
157
+ region = body.match(/<Region>(.+?)<\/Region>/)[1]
158
+ if region.nil? || region == ""
159
+ raise "couldn't get region from body: #{body}"
160
+ else
161
+ region
162
+ end
163
+ end
164
+
165
+ def log_warning(context, actual_region)
166
+ msg = "S3 client configured for #{context.config.region.inspect} " +
167
+ "but the bucket #{context.params[:bucket].inspect} is in " +
168
+ "#{actual_region.inspect}; Please configure the proper region " +
169
+ "to avoid multiple unnecessary redirects and signing attempts\n"
170
+ if logger = context.config.logger
171
+ logger.warn(msg)
172
+ else
173
+ warn(msg)
174
+ end
175
+ end
176
+
177
+ end
178
+
179
+ class << self
180
+
181
+ # @option options [required, String] :region
182
+ # @option options [required, #credentials] :credentials
183
+ # @api private
184
+ def build_v4_signer(options = {})
185
+ Aws::Sigv4::Signer.new({
186
+ service: 's3',
187
+ region: options[:region],
188
+ credentials_provider: options[:credentials],
189
+ uri_escape_path: false,
190
+ unsigned_headers: ['content-length'],
191
+ })
192
+ end
193
+
194
+ def new_hostname(context, region)
195
+ bucket = context.params[:bucket]
196
+ if region == 'us-east-1'
197
+ "#{bucket}.s3.amazonaws.com"
198
+ else
199
+ endpoint = Aws::Partitions::EndpointProvider.resolve(region, 's3')
200
+ bucket + '.' + URI.parse(endpoint).host
201
+ end
202
+ end
203
+
204
+ end
205
+ end
206
+ end
207
+ end
208
+ end