aws-sdk 1.6.2 → 1.6.3
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.
- data/lib/aws/core.rb +13 -2
- data/lib/aws/core/autoloader.rb +1 -1
- data/lib/aws/core/client.rb +69 -30
- data/lib/aws/core/configuration.rb +12 -1
- data/lib/aws/core/http/handler.rb +28 -16
- data/lib/aws/core/http/net_http_handler.rb +31 -11
- data/lib/aws/core/http/request.rb +52 -16
- data/lib/aws/core/http/response.rb +20 -16
- data/lib/aws/core/indifferent_hash.rb +14 -14
- data/lib/aws/core/query_client.rb +1 -0
- data/lib/aws/core/response.rb +32 -14
- data/lib/aws/core/signature/version_2.rb +1 -0
- data/lib/aws/core/signature/version_4.rb +16 -16
- data/lib/aws/dynamo_db/client.rb +2 -2
- data/lib/aws/dynamo_db/request.rb +0 -6
- data/lib/aws/ec2/security_group/ip_permission.rb +4 -1
- data/lib/aws/rails.rb +10 -10
- data/lib/aws/s3.rb +44 -29
- data/lib/aws/s3/bucket.rb +171 -6
- data/lib/aws/s3/cipher_io.rb +119 -0
- data/lib/aws/s3/client.rb +75 -45
- data/lib/aws/s3/config.rb +6 -0
- data/lib/aws/s3/data_options.rb +136 -49
- data/lib/aws/s3/encryption_utils.rb +144 -0
- data/lib/aws/s3/errors.rb +14 -0
- data/lib/aws/s3/multipart_upload.rb +7 -4
- data/lib/aws/s3/object_collection.rb +2 -2
- data/lib/aws/s3/policy.rb +1 -1
- data/lib/aws/s3/request.rb +21 -33
- data/lib/aws/s3/s3_object.rb +797 -237
- data/lib/aws/simple_email_service/request.rb +0 -2
- data/lib/aws/simple_workflow/request.rb +0 -3
- data/lib/net/http/connection_pool.rb +63 -75
- data/lib/net/http/connection_pool/connection.rb +69 -15
- data/lib/net/http/connection_pool/session.rb +39 -6
- metadata +4 -2
data/lib/aws/s3.rb
CHANGED
@@ -26,7 +26,7 @@ module AWS
|
|
26
26
|
# * {Amazon S3}[http://aws.amazon.com/s3/]
|
27
27
|
# * {Amazon S3 Documentation}[http://aws.amazon.com/documentation/s3/]
|
28
28
|
#
|
29
|
-
#
|
29
|
+
# = Credentials
|
30
30
|
#
|
31
31
|
# You can setup default credentials for all AWS services via
|
32
32
|
# AWS.config:
|
@@ -34,63 +34,76 @@ module AWS
|
|
34
34
|
# AWS.config(
|
35
35
|
# :access_key_id => 'YOUR_ACCESS_KEY_ID',
|
36
36
|
# :secret_access_key => 'YOUR_SECRET_ACCESS_KEY')
|
37
|
-
#
|
37
|
+
#
|
38
38
|
# Or you can set them directly on the S3 interface:
|
39
39
|
#
|
40
40
|
# s3 = AWS::S3.new(
|
41
41
|
# :access_key_id => 'YOUR_ACCESS_KEY_ID',
|
42
42
|
# :secret_access_key => 'YOUR_SECRET_ACCESS_KEY')
|
43
43
|
#
|
44
|
-
#
|
44
|
+
# = Buckets
|
45
45
|
#
|
46
|
-
# S3
|
46
|
+
# Before you can upload files to S3, you need to create a bucket.
|
47
47
|
#
|
48
|
-
#
|
48
|
+
# s3 = AWS::S3.new
|
49
|
+
# bucket = s3.buckets.create('my-bucket')
|
49
50
|
#
|
50
|
-
#
|
51
|
+
# If a bucket already exists, you can get a reference to the bucket.
|
51
52
|
#
|
52
|
-
#
|
53
|
+
# bucket = s3.buckets['my-bucket'] # no request made
|
53
54
|
#
|
54
|
-
#
|
55
|
-
# bucket = s3.buckets['mybucket']
|
55
|
+
# You can also enumerate all buckets in your account.
|
56
56
|
#
|
57
|
-
# Listing buckets:
|
58
|
-
#
|
59
57
|
# s3.buckets.each do |bucket|
|
60
58
|
# puts bucket.name
|
61
59
|
# end
|
62
60
|
#
|
63
|
-
# See {
|
64
|
-
# with
|
61
|
+
# See {BucketCollection} and {Bucket} for more information on working
|
62
|
+
# with buckets.
|
65
63
|
#
|
66
|
-
#
|
64
|
+
# = Objects
|
67
65
|
#
|
68
|
-
#
|
66
|
+
# Buckets contain objects. Each object in a bucket has a unique key.
|
69
67
|
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
68
|
+
# == Getting an Object
|
69
|
+
#
|
70
|
+
# If the object already exists, you can get a reference to the object.
|
73
71
|
#
|
74
|
-
#
|
75
|
-
#
|
72
|
+
# # makes no request, returns an AWS::S3::S3Object
|
73
|
+
# obj = bucket.objects['key']
|
76
74
|
#
|
77
|
-
# == Reading and Writing
|
75
|
+
# == Reading and Writing an Object
|
78
76
|
#
|
79
|
-
#
|
77
|
+
# The example above returns an {S3Object}. You call {S3Object#write} and
|
78
|
+
# {S3Object#read} to upload to and download from S3 respectively.
|
80
79
|
#
|
81
|
-
#
|
80
|
+
# # streaming upload a file to S3
|
81
|
+
# obj.write(Pathname.new('/path/to/file.txt'))
|
82
82
|
#
|
83
|
-
#
|
83
|
+
# # streaming download from S3 to a file on disk
|
84
|
+
# File.open('file.txt', 'w') do |file|
|
85
|
+
# obj.read do |chunk|
|
86
|
+
# file.write(chunk)
|
87
|
+
# end
|
88
|
+
# end
|
89
|
+
#
|
90
|
+
# == Enumerating Objects
|
84
91
|
#
|
85
|
-
#
|
92
|
+
# You can enumerate objects in your buckets.
|
86
93
|
#
|
87
|
-
#
|
94
|
+
# # enumerate ALL objects in the bucket (even if the bucket contains
|
95
|
+
# # more than 1k objects)
|
96
|
+
# bucket.objects.each do |obj|
|
97
|
+
# puts obj.key
|
98
|
+
# end
|
88
99
|
#
|
89
|
-
#
|
90
|
-
#
|
100
|
+
# # enumerate at most 20 objects with the given prefix
|
101
|
+
# bucket.objects.with_prefix('photos/').each(:limit => 20).each do |photo|
|
102
|
+
# puts photo.key
|
91
103
|
# end
|
92
104
|
#
|
93
|
-
# See {S3Object} for more information on
|
105
|
+
# See {ObjectCollection} and {S3Object} for more information on working
|
106
|
+
# with objects.
|
94
107
|
#
|
95
108
|
class S3
|
96
109
|
|
@@ -104,6 +117,8 @@ module AWS
|
|
104
117
|
autoload :BucketVersionCollection, 'bucket_version_collection'
|
105
118
|
autoload :Client, 'client'
|
106
119
|
autoload :DataOptions, 'data_options'
|
120
|
+
autoload :EncryptionUtils, 'encryption_utils'
|
121
|
+
autoload :CipherIO, 'cipher_io'
|
107
122
|
autoload :Errors, 'errors'
|
108
123
|
autoload :MultipartUpload, 'multipart_upload'
|
109
124
|
autoload :MultipartUploadCollection, 'multipart_upload_collection'
|
data/lib/aws/s3/bucket.rb
CHANGED
@@ -14,15 +14,180 @@
|
|
14
14
|
module AWS
|
15
15
|
class S3
|
16
16
|
|
17
|
-
# Represents a
|
17
|
+
# Represents a bucket in S3.
|
18
18
|
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
# bucket = s3.buckets.create('mybucket')
|
19
|
+
# = Creating Buckets
|
22
20
|
#
|
23
|
-
#
|
21
|
+
# You create a bucket by name. Bucket names must be globally unique
|
22
|
+
# and must be DNS compatible.
|
24
23
|
#
|
25
|
-
#
|
24
|
+
# s3 = AWS::S3.new
|
25
|
+
# bucket = s3.buckets.create('dns-compat-bucket-name')
|
26
|
+
#
|
27
|
+
# = Getting a Bucket
|
28
|
+
#
|
29
|
+
# You can create a reference to a bucket, given its name.
|
30
|
+
#
|
31
|
+
# bucket = s3.buckets['bucket-name'] # makes no request
|
32
|
+
# bucket.exists? #=> returns true/false
|
33
|
+
#
|
34
|
+
# = Enumerating Buckets
|
35
|
+
#
|
36
|
+
# The {BucketCollection} class is enumerable.
|
37
|
+
#
|
38
|
+
# s3.buckets.each do |bucket|
|
39
|
+
# puts bucket.name
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# = Deleting a Bucket
|
43
|
+
#
|
44
|
+
# You can delete an empty bucket you own.
|
45
|
+
#
|
46
|
+
# bucket = s3.buckets.create('my-temp-bucket')
|
47
|
+
# bucket.objects['abc'].write('xyz')
|
48
|
+
#
|
49
|
+
# bucket.clear! # deletes all object versions in batches
|
50
|
+
# bucket.delete
|
51
|
+
#
|
52
|
+
# You can alternatively call {#delete!} which will clear
|
53
|
+
# the bucket for your first.
|
54
|
+
#
|
55
|
+
# bucket.delete!
|
56
|
+
#
|
57
|
+
# = Objects
|
58
|
+
#
|
59
|
+
# Given a bucket you can access its objects, either by key or by
|
60
|
+
# enumeration.
|
61
|
+
#
|
62
|
+
# bucket.objects['key'] #=> makes no request, returns an S3Object
|
63
|
+
#
|
64
|
+
# bucket.objects.each do |obj|
|
65
|
+
# puts obj.key
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# See {ObjectCollection} and {S3Object} for more information on working
|
69
|
+
# with objects.
|
70
|
+
#
|
71
|
+
# = Bucket Policies and ACLs
|
72
|
+
#
|
73
|
+
# You can control access to your bucket and its contents a number
|
74
|
+
# of ways. You can specify a bucket ACL (access control list)
|
75
|
+
# or a bucket policy.
|
76
|
+
#
|
77
|
+
# == ACLs
|
78
|
+
#
|
79
|
+
# ACLs control access to your bucket and its contents via a list of
|
80
|
+
# grants and grantees.
|
81
|
+
#
|
82
|
+
# === Canned ACLs
|
83
|
+
#
|
84
|
+
# The simplest way to specify an ACL is to use one of Amazon's "canned"
|
85
|
+
# ACLs. Amazon accepts the following canned ACLs:
|
86
|
+
#
|
87
|
+
# * +:private+
|
88
|
+
# * +:public_read+
|
89
|
+
# * +:public_read_write+
|
90
|
+
# * +:authenticated_read+
|
91
|
+
# * +:bucket_owner_read+
|
92
|
+
# * +:bucket_owner_full_control+
|
93
|
+
#
|
94
|
+
# You can specify a the ACL at bucket creation or later update a bucket.
|
95
|
+
#
|
96
|
+
# # at create time, defaults to :private when not specified
|
97
|
+
# bucket = s3.buckets.create('name', :acl => :public_read)
|
98
|
+
#
|
99
|
+
# # replacing an existing bucket ACL
|
100
|
+
# bucket.acl = :private
|
101
|
+
#
|
102
|
+
# === Grants
|
103
|
+
#
|
104
|
+
# Alternatively you can specify a hash of grants. Each entry in the
|
105
|
+
# +:grant+ hash has a grant (key) and a list of grantees (values).
|
106
|
+
# Valid grant keys are:
|
107
|
+
#
|
108
|
+
# * +:grant_read+
|
109
|
+
# * +:grant_write+
|
110
|
+
# * +:grant_read_acp+
|
111
|
+
# * +:grant_write_acp+
|
112
|
+
# * +:grant_full_control+
|
113
|
+
#
|
114
|
+
# Each grantee can be a String, Hash or array of strings or hashes.
|
115
|
+
# The following example uses grants to provide public read
|
116
|
+
# to everyone while providing full control to a user by email address
|
117
|
+
# and to another by their account id (cannonical user id).
|
118
|
+
#
|
119
|
+
# bucket = s3.buckets.create('name', :grants => {
|
120
|
+
# :grant_read => [
|
121
|
+
# { :uri => "http://acs.amazonaws.com/groups/global/AllUsers" },
|
122
|
+
# ],
|
123
|
+
# :grant_full_control => [
|
124
|
+
# { :id => 'abc...mno' } # cannonical user id
|
125
|
+
# { :email_address => 'foo@bar.com' }, # email address
|
126
|
+
# ]
|
127
|
+
# })
|
128
|
+
#
|
129
|
+
# === ACL Object
|
130
|
+
#
|
131
|
+
# Lastly, you can build an ACL object and use a Ruby DSL to specify grants
|
132
|
+
# and grantees. See {ACLObject} for more information.
|
133
|
+
#
|
134
|
+
# # updating an existing bucket acl using ACLObject
|
135
|
+
# bucket.acl.change do |acl|
|
136
|
+
# acl.grants.reject! do |g|
|
137
|
+
# g.grantee.canonical_user_id != bucket.owner.id
|
138
|
+
# end
|
139
|
+
# end
|
140
|
+
#
|
141
|
+
# == Policies
|
142
|
+
#
|
143
|
+
# You can also work with bucket policies.
|
144
|
+
#
|
145
|
+
# policy = AWS::S3::Policy.new
|
146
|
+
# policy.allow(
|
147
|
+
# :actions => [:put_object, :get_object]
|
148
|
+
# :resources => [bucket]
|
149
|
+
# :principals => :any)
|
150
|
+
#
|
151
|
+
# bucket.policy = policy
|
152
|
+
#
|
153
|
+
# See {Core::Policy} and {S3::Policy} for more information on build
|
154
|
+
# policy objects.
|
155
|
+
#
|
156
|
+
# = Versioned Buckets
|
157
|
+
#
|
158
|
+
# You can enable versioning on a bucket you control. When versioning
|
159
|
+
# is enabled, S3 will keep track of each version of each object you
|
160
|
+
# write to the bucket (even deletions).
|
161
|
+
#
|
162
|
+
# bucket.versioning_enabled? #=> false
|
163
|
+
# bucket.enable_versioning
|
164
|
+
# # there is also a #disable_versioning method
|
165
|
+
#
|
166
|
+
# obj = bucket.objects['my-obj']
|
167
|
+
# obj.write('a')
|
168
|
+
# obj.write('b')
|
169
|
+
# obj.delete
|
170
|
+
# obj.write('c')
|
171
|
+
#
|
172
|
+
# obj.versions.each do |obj_version|
|
173
|
+
# if obj_version.delete_marker?
|
174
|
+
# puts obj_version.read
|
175
|
+
# else
|
176
|
+
# puts "- DELETE MARKER"
|
177
|
+
# end
|
178
|
+
# end
|
179
|
+
#
|
180
|
+
# Alternatively you can enumerate all versions of all objects in your
|
181
|
+
# bucket.
|
182
|
+
#
|
183
|
+
# bucket.versions.each do |obj_version|
|
184
|
+
# puts obj_version.key + " : " + obj_version.version_id
|
185
|
+
# end
|
186
|
+
#
|
187
|
+
# See {BucketVersionCollection}, {ObjectVersionCollection} and
|
188
|
+
# {ObjectVersion} for more information on working with objects in
|
189
|
+
# a versioned bucket. Also see the S3 documentation for information
|
190
|
+
# on object versioning.
|
26
191
|
#
|
27
192
|
class Bucket
|
28
193
|
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# Copyright 2011-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You
|
4
|
+
# may not use this file except in compliance with the License. A copy of
|
5
|
+
# the License is located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the "license" file accompanying this file. This file is
|
10
|
+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
11
|
+
# ANY KIND, either express or implied. See the License for the specific
|
12
|
+
# language governing permissions and limitations under the License.
|
13
|
+
|
14
|
+
module AWS
|
15
|
+
class S3
|
16
|
+
|
17
|
+
# @private
|
18
|
+
class CipherIO
|
19
|
+
|
20
|
+
def initialize cipher, stream, stream_size = nil
|
21
|
+
|
22
|
+
@stream = stream
|
23
|
+
@stream_size = stream_size
|
24
|
+
@orig_cipher = cipher.clone
|
25
|
+
|
26
|
+
reset_cipher
|
27
|
+
|
28
|
+
# add a #rewind method if the original stream can be rewound
|
29
|
+
if @stream.respond_to?(:rewind)
|
30
|
+
Core::MetaUtils.extend_method(self, :rewind) do
|
31
|
+
reset_cipher
|
32
|
+
@stream.rewind
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# add a #size method if the stream size is known
|
37
|
+
if stream_size
|
38
|
+
Core::MetaUtils.extend_method(self, :size) do
|
39
|
+
EncryptionUtils.get_encrypted_size(@stream_size)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
# @return [String] Returns the requested number of bytes. If no byte
|
46
|
+
# amount is given, it will return the entire body of encrypted data
|
47
|
+
def read bytes = nil
|
48
|
+
if bytes
|
49
|
+
(@eof) ? nil : read_chunk(bytes)
|
50
|
+
else
|
51
|
+
(@eof) ? "" : read_all()
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [Boolean] Returns +true+ when the entire stream has been read.
|
56
|
+
def eof?
|
57
|
+
@eof
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
attr_reader :cipher
|
63
|
+
|
64
|
+
# Sets the CipherIO in a reset state without having to know anything
|
65
|
+
# about the cipher
|
66
|
+
def reset_cipher
|
67
|
+
@cipher = @orig_cipher.clone
|
68
|
+
@eof = false
|
69
|
+
@final = nil
|
70
|
+
end
|
71
|
+
|
72
|
+
# @return [String] Returns an encrytped chunk
|
73
|
+
def read_chunk bytes
|
74
|
+
unless @final
|
75
|
+
# If given a number of bytes, read it out and work out encryption
|
76
|
+
# issues
|
77
|
+
chunk = @stream.read(bytes)
|
78
|
+
|
79
|
+
# If there is nothing, finish the encryption
|
80
|
+
if chunk and chunk.length > 0
|
81
|
+
handle_finish(bytes, cipher.update(chunk))
|
82
|
+
else
|
83
|
+
@eof = true
|
84
|
+
cipher.final
|
85
|
+
end
|
86
|
+
# Read as much as possible if not given a byte size
|
87
|
+
else
|
88
|
+
@eof = true
|
89
|
+
@final
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# @return [String] Returns the entire encrypted data
|
94
|
+
def read_all
|
95
|
+
@eof = true
|
96
|
+
body = @stream.read()
|
97
|
+
data = (body and body.length > 0) ? cipher.update(body) : ""
|
98
|
+
data << cipher.final
|
99
|
+
end
|
100
|
+
|
101
|
+
# Figures out how much of the final block goes into the current chunk
|
102
|
+
# and adds it.
|
103
|
+
# @return [String] Returns the encrypted chunk with possible padding.
|
104
|
+
def handle_finish(bytes, chunk)
|
105
|
+
free_space = bytes - chunk.size
|
106
|
+
|
107
|
+
if free_space > 0
|
108
|
+
@final = cipher.final
|
109
|
+
chunk << @final[0..free_space-1]
|
110
|
+
@final = @final[free_space-1..@final.size-1]
|
111
|
+
@eof = true unless @final and @final.size > 0
|
112
|
+
end
|
113
|
+
|
114
|
+
chunk
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
data/lib/aws/s3/client.rb
CHANGED
@@ -295,7 +295,7 @@ module AWS
|
|
295
295
|
|
296
296
|
process_response do |response|
|
297
297
|
regex = />(.*)<\/LocationConstraint>/
|
298
|
-
matches = response.http_response.body.match(regex)
|
298
|
+
matches = response.http_response.body.to_s.match(regex)
|
299
299
|
response.data[:location_constraint] = matches ? matches[1] : nil
|
300
300
|
end
|
301
301
|
|
@@ -573,10 +573,14 @@ module AWS
|
|
573
573
|
# * +:private+
|
574
574
|
# * +:public_read+
|
575
575
|
# * ...
|
576
|
-
# @option options [
|
576
|
+
# @option options [String] :storage_class+ ('STANDARD')
|
577
577
|
# Controls whether Reduced Redundancy Storage is enabled for
|
578
|
-
# the object. Valid values are
|
579
|
-
#
|
578
|
+
# the object. Valid values are 'STANDARD' and
|
579
|
+
# 'REDUCED_REDUNDANCY'.
|
580
|
+
# @option options [Symbol,String] :server_side_encryption (nil) The
|
581
|
+
# algorithm used to encrypt the object on the server side
|
582
|
+
# (e.g. :aes256).
|
583
|
+
# object on the server side, e.g. +:aes256+)
|
580
584
|
# @option options [String] :cache_control
|
581
585
|
# Can be used to specify caching behavior.
|
582
586
|
# @option options [String] :content_disposition
|
@@ -610,19 +614,20 @@ module AWS
|
|
610
614
|
:content_disposition => 'Content-Disposition',
|
611
615
|
:content_encoding => 'Content-Encoding',
|
612
616
|
:content_type => 'Content-Type',
|
613
|
-
:storage_class => 'x-amz-storage-class',
|
614
|
-
:server_side_encryption => 'x-amz-server-side-encryption',
|
615
617
|
:expires => 'Expires'
|
616
618
|
}) do
|
617
619
|
|
618
|
-
configure_request do |request, options
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
set_request_data(request, options, block)
|
620
|
+
configure_request do |request, options|
|
621
|
+
|
622
|
+
options = compute_write_options(options)
|
623
|
+
set_body_stream_and_content_length(request, options)
|
624
|
+
|
624
625
|
request.metadata = options[:metadata]
|
625
626
|
request.storage_class = options[:storage_class]
|
627
|
+
request.server_side_encryption = options[:server_side_encryption]
|
628
|
+
|
629
|
+
super(request, options)
|
630
|
+
|
626
631
|
end
|
627
632
|
|
628
633
|
process_response do |response|
|
@@ -637,6 +642,7 @@ module AWS
|
|
637
642
|
end
|
638
643
|
|
639
644
|
add_sse_to_response(response)
|
645
|
+
|
640
646
|
end
|
641
647
|
|
642
648
|
simulate_response do |response|
|
@@ -826,8 +832,13 @@ module AWS
|
|
826
832
|
# @option options [String] :content_disposition
|
827
833
|
# @option options [String] :content_encoding
|
828
834
|
# @option options [String] :content_type
|
829
|
-
# @option options [String] :storage_class
|
830
|
-
#
|
835
|
+
# @option options [String] :storage_class+ ('STANDARD')
|
836
|
+
# Controls whether Reduced Redundancy Storage is enabled for
|
837
|
+
# the object. Valid values are 'STANDARD' and
|
838
|
+
# 'REDUCED_REDUNDANCY'.
|
839
|
+
# @option options [Symbol,String] :server_side_encryption (nil) The
|
840
|
+
# algorithm used to encrypt the object on the server side
|
841
|
+
# (e.g. :aes256).
|
831
842
|
# @option options [String] :expires
|
832
843
|
# @option options [String] :acl A canned ACL (e.g. 'private',
|
833
844
|
# 'public-read', etc). See the S3 API documentation for
|
@@ -851,23 +862,20 @@ module AWS
|
|
851
862
|
:content_disposition => 'Content-Disposition',
|
852
863
|
:content_encoding => 'Content-Encoding',
|
853
864
|
:content_type => 'Content-Type',
|
854
|
-
:storage_class => 'x-amz-storage-class',
|
855
|
-
:server_side_encryption => 'x-amz-server-side-encryption',
|
856
865
|
:expires => 'Expires'
|
857
866
|
}) do
|
858
867
|
|
859
868
|
configure_request do |req, options|
|
860
|
-
options[:server_side_encryption] =
|
861
|
-
options[:server_side_encryption].to_s.upcase if
|
862
|
-
options[:server_side_encryption].kind_of?(Symbol)
|
863
|
-
super(req, options)
|
864
869
|
req.metadata = options[:metadata]
|
865
870
|
req.storage_class = options[:storage_class]
|
871
|
+
req.server_side_encryption = options[:server_side_encryption]
|
872
|
+
super(req, options)
|
866
873
|
end
|
867
874
|
|
868
875
|
process_response do |response|
|
869
876
|
add_sse_to_response(response)
|
870
877
|
end
|
878
|
+
|
871
879
|
end
|
872
880
|
|
873
881
|
# @overload list_multipart_uploads(options = {})
|
@@ -933,26 +941,30 @@ module AWS
|
|
933
941
|
# @param [Hash] options
|
934
942
|
# @option options [required,String] :bucket_name
|
935
943
|
# @option options [required,String] :key
|
944
|
+
# @option options [required,String] :upload_id
|
945
|
+
# @option options [required,Integer] :part_number
|
936
946
|
# @option options [required,String,Pathname,File,IO] :data
|
937
947
|
# The data to upload. This can be provided as a string,
|
938
948
|
# a Pathname object, or any object that responds to
|
939
949
|
# +#read+ and +#eof?+ (e.g. IO, File, Tempfile, StringIO, etc).
|
940
|
-
# @option options [required,String] :upload_id
|
941
|
-
# @option options [required,Integer] :part_number
|
942
950
|
# @return [Core::Response]
|
943
951
|
object_method(:upload_part, :put,
|
944
952
|
:header_options => {
|
945
953
|
:content_md5 => 'Content-MD5'
|
946
954
|
}) do
|
947
|
-
configure_request do |request, options
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
set_request_data(request, options, block)
|
955
|
+
configure_request do |request, options|
|
956
|
+
|
957
|
+
options = compute_write_options(options)
|
958
|
+
set_body_stream_and_content_length(request, options)
|
959
|
+
|
960
|
+
require_upload_id!(options[:upload_id])
|
954
961
|
request.add_param('uploadId', options[:upload_id])
|
962
|
+
|
963
|
+
require_part_number!(options[:part_number])
|
955
964
|
request.add_param('partNumber', options[:part_number])
|
965
|
+
|
966
|
+
super(request, options)
|
967
|
+
|
956
968
|
end
|
957
969
|
|
958
970
|
process_response do |response|
|
@@ -1051,6 +1063,13 @@ module AWS
|
|
1051
1063
|
# @option options [String] :acl A canned ACL (e.g. 'private',
|
1052
1064
|
# 'public-read', etc). See the S3 API documentation for
|
1053
1065
|
# a complete list of valid values.
|
1066
|
+
# @option options [Symbol,String] :server_side_encryption (nil) The
|
1067
|
+
# algorithm used to encrypt the object on the server side
|
1068
|
+
# (e.g. :aes256).
|
1069
|
+
# @option options [String] :storage_class+ ('STANDARD')
|
1070
|
+
# Controls whether Reduced Redundancy Storage is enabled for
|
1071
|
+
# the object. Valid values are 'STANDARD' and
|
1072
|
+
# 'REDUCED_REDUNDANCY'.
|
1054
1073
|
# @option options [String] :grant_read
|
1055
1074
|
# @option options [String] :grant_write
|
1056
1075
|
# @option options [String] :grant_read_acp
|
@@ -1067,25 +1086,21 @@ module AWS
|
|
1067
1086
|
:copy_source => 'x-amz-copy-source',
|
1068
1087
|
:cache_control => 'Cache-Control',
|
1069
1088
|
:metadata_directive => 'x-amz-metadata-directive',
|
1070
|
-
:storage_class => 'x-amz-storage-class',
|
1071
|
-
:server_side_encryption => 'x-amz-server-side-encryption',
|
1072
1089
|
:content_type => 'Content-Type',
|
1073
1090
|
}) do
|
1074
1091
|
|
1075
1092
|
configure_request do |req, options|
|
1076
|
-
|
1077
|
-
# TODO : validate storage class STANDARD / REDUCED_REDUNDANCY
|
1078
|
-
# TODO : add validations for storage class in other places used
|
1093
|
+
|
1079
1094
|
validate!(:copy_source, options[:copy_source]) do
|
1080
1095
|
"may not be blank" if options[:copy_source].to_s.empty?
|
1081
1096
|
end
|
1097
|
+
|
1082
1098
|
options = options.merge(:copy_source => escape_path(options[:copy_source]))
|
1083
|
-
options[:server_side_encryption] =
|
1084
|
-
options[:server_side_encryption].to_s.upcase if
|
1085
|
-
options[:server_side_encryption].kind_of?(Symbol)
|
1086
1099
|
super(req, options)
|
1087
1100
|
req.metadata = options[:metadata]
|
1088
1101
|
req.storage_class = options[:storage_class]
|
1102
|
+
req.server_side_encryption = options[:server_side_encryption]
|
1103
|
+
|
1089
1104
|
if options[:version_id]
|
1090
1105
|
req.headers['x-amz-copy-source'] += "?versionId=#{options[:version_id]}"
|
1091
1106
|
end
|
@@ -1130,20 +1145,15 @@ module AWS
|
|
1130
1145
|
end
|
1131
1146
|
end
|
1132
1147
|
|
1133
|
-
def
|
1148
|
+
def retryable_error? response
|
1134
1149
|
super or
|
1135
|
-
response.request_type == :complete_multipart_upload &&
|
1136
|
-
extract_error_details(response)
|
1150
|
+
(response.request_type == :complete_multipart_upload &&
|
1151
|
+
extract_error_details(response))
|
1137
1152
|
# complete multipart upload can return an error inside a
|
1138
1153
|
# 200 level response -- this forces us to parse the
|
1139
1154
|
# response for errors every time
|
1140
1155
|
end
|
1141
1156
|
|
1142
|
-
def set_request_data request, options, block
|
1143
|
-
request.body_stream = data_stream_from(options, &block)
|
1144
|
-
request.headers['Content-Length'] = content_length_from(options)
|
1145
|
-
end
|
1146
|
-
|
1147
1157
|
def new_request
|
1148
1158
|
req = S3::Request.new
|
1149
1159
|
req.force_path_style = config.s3_force_path_style?
|
@@ -1320,12 +1330,32 @@ module AWS
|
|
1320
1330
|
end
|
1321
1331
|
end
|
1322
1332
|
|
1333
|
+
def set_body_stream_and_content_length request, options
|
1334
|
+
|
1335
|
+
unless options[:content_length]
|
1336
|
+
msg = "S3 requires a content-length header, unable to determine "
|
1337
|
+
msg << "the content length of the data provided, please set "
|
1338
|
+
msg << ":content_length"
|
1339
|
+
raise ArgumentError, msg
|
1340
|
+
end
|
1341
|
+
|
1342
|
+
request.headers['content-length'] = options[:content_length]
|
1343
|
+
request.body_stream = options[:data]
|
1344
|
+
|
1345
|
+
end
|
1346
|
+
|
1323
1347
|
def require_upload_id!(upload_id)
|
1324
1348
|
validate!("upload_id", upload_id) do
|
1325
1349
|
"must not be blank" if upload_id.to_s.empty?
|
1326
1350
|
end
|
1327
1351
|
end
|
1328
1352
|
|
1353
|
+
def require_part_number! part_number
|
1354
|
+
validate!("part_number", part_number) do
|
1355
|
+
"must not be blank" if part_number.to_s.empty?
|
1356
|
+
end
|
1357
|
+
end
|
1358
|
+
|
1329
1359
|
def validate_parts!(parts)
|
1330
1360
|
validate!("parts", parts) do
|
1331
1361
|
if !parts.kind_of?(Array)
|