aws-sdk 1.2.3 → 1.2.4
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 +1 -1
- data/lib/aws/core/http/net_http_handler.rb +21 -62
- data/lib/aws/record/attribute_macros.rb +28 -4
- data/lib/aws/record/attributes/date.rb +89 -0
- data/lib/aws/record/base.rb +41 -4
- data/lib/aws/record/finder_methods.rb +7 -5
- data/lib/aws/record/scope.rb +32 -5
- data/lib/aws/s3/bucket.rb +14 -5
- data/lib/aws/s3/bucket_version_collection.rb +7 -11
- data/lib/aws/s3/client.rb +37 -1
- data/lib/aws/s3/client/xml.rb +8 -1
- data/lib/aws/s3/errors.rb +14 -0
- data/lib/aws/s3/multipart_upload_collection.rb +0 -3
- data/lib/aws/s3/object_collection.rb +182 -6
- data/lib/aws/s3/paginated_collection.rb +21 -40
- data/lib/aws/s3/prefix_and_delimiter_collection.rb +0 -7
- data/lib/aws/s3/presigned_post.rb +26 -11
- data/lib/aws/s3/request.rb +1 -1
- data/lib/aws/s3/s3_object.rb +10 -4
- data/lib/aws/s3/uploaded_part_collection.rb +3 -1
- data/lib/net/http/connection_pool.rb +193 -0
- data/lib/net/http/connection_pool/connection.rb +132 -0
- data/lib/net/http/connection_pool/session.rb +93 -0
- metadata +8 -4
@@ -19,13 +19,6 @@ module AWS
|
|
19
19
|
|
20
20
|
include PrefixedCollection
|
21
21
|
|
22
|
-
def each(options = {}, &block)
|
23
|
-
each_page(options) do |page|
|
24
|
-
each_member_in_page(page, &block)
|
25
|
-
end
|
26
|
-
nil
|
27
|
-
end
|
28
|
-
|
29
22
|
# @see Bucket#as_tree
|
30
23
|
def as_tree options = {}
|
31
24
|
Tree.new(self, { :prefix => prefix }.merge(options))
|
@@ -340,15 +340,21 @@ module AWS
|
|
340
340
|
# long as they are described by a policy condition (see
|
341
341
|
# {#where}).
|
342
342
|
def fields
|
343
|
-
signature =
|
344
|
-
config.signer.sign(policy, "sha1")
|
345
343
|
|
346
|
-
|
344
|
+
signature = config.signer.sign(policy, "sha1")
|
345
|
+
|
346
|
+
fields = {
|
347
347
|
"AWSAccessKeyId" => config.signer.access_key_id,
|
348
348
|
"key" => key,
|
349
349
|
"policy" => policy,
|
350
350
|
"signature" => signature
|
351
351
|
}.merge(optional_fields)
|
352
|
+
|
353
|
+
fields["x-amz-security-token"] = config.signer.session_token if
|
354
|
+
config.signer.session_token
|
355
|
+
|
356
|
+
fields.merge(optional_fields)
|
357
|
+
|
352
358
|
end
|
353
359
|
|
354
360
|
# @private
|
@@ -482,14 +488,23 @@ module AWS
|
|
482
488
|
# @private
|
483
489
|
private
|
484
490
|
def generate_conditions
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
491
|
+
|
492
|
+
conditions = self.conditions.inject([]) do |list, (field, field_conds)|
|
493
|
+
list + field_conds
|
494
|
+
end
|
495
|
+
|
496
|
+
conditions << { "bucket" => bucket.name }
|
497
|
+
conditions += key_conditions
|
498
|
+
conditions += optional_fields.map { |(n, v)| Hash[[[n, v]]] }
|
499
|
+
conditions += range_conditions
|
500
|
+
conditions += ignored_conditions
|
501
|
+
|
502
|
+
if config.signer.session_token
|
503
|
+
conditions << {"x-amz-security-token" => config.signer.session_token}
|
504
|
+
end
|
505
|
+
|
506
|
+
conditions
|
507
|
+
|
493
508
|
end
|
494
509
|
|
495
510
|
# @private
|
data/lib/aws/s3/request.rb
CHANGED
data/lib/aws/s3/s3_object.rb
CHANGED
@@ -410,13 +410,12 @@ module AWS
|
|
410
410
|
upload = multipart_uploads.create(options)
|
411
411
|
|
412
412
|
if block_given?
|
413
|
-
result = nil
|
414
413
|
begin
|
415
414
|
yield(upload)
|
416
|
-
|
417
|
-
|
415
|
+
upload.close
|
416
|
+
rescue
|
417
|
+
upload.abort
|
418
418
|
end
|
419
|
-
result
|
420
419
|
else
|
421
420
|
upload
|
422
421
|
end
|
@@ -488,6 +487,10 @@ module AWS
|
|
488
487
|
# option in the current configuration; for more information,
|
489
488
|
# see {AWS.config}.
|
490
489
|
#
|
490
|
+
# @option options :cache_control [String] Can be used to specify
|
491
|
+
# caching behavior. See
|
492
|
+
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
|
493
|
+
#
|
491
494
|
# @return [nil]
|
492
495
|
def copy_from source, options = {}
|
493
496
|
|
@@ -524,6 +527,8 @@ module AWS
|
|
524
527
|
copy_opts[:server_side_encryption] =
|
525
528
|
options[:server_side_encryption] if
|
526
529
|
options.key?(:server_side_encryption)
|
530
|
+
copy_opts[:cache_control] = options[:cache_control] if
|
531
|
+
options[:cache_control]
|
527
532
|
add_configured_write_options(copy_opts)
|
528
533
|
|
529
534
|
if options[:reduced_redundancy]
|
@@ -641,6 +646,7 @@ module AWS
|
|
641
646
|
# the object ETag matches the provided value.
|
642
647
|
#
|
643
648
|
# @option options [Range] :range A byte range to read data from
|
649
|
+
#
|
644
650
|
def read(options = {}, &blk)
|
645
651
|
options[:bucket_name] = bucket.name
|
646
652
|
options[:key] = key
|
@@ -0,0 +1,193 @@
|
|
1
|
+
# Copyright 2011 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
|
+
require 'net/http/connection_pool/session'
|
15
|
+
require 'net/http/connection_pool/connection'
|
16
|
+
require 'thread'
|
17
|
+
|
18
|
+
# @private
|
19
|
+
class Net::HTTP::ConnectionPool
|
20
|
+
|
21
|
+
SOCKET_ERRORS = [
|
22
|
+
EOFError,
|
23
|
+
IOError,
|
24
|
+
Errno::ECONNABORTED,
|
25
|
+
Errno::ECONNRESET,
|
26
|
+
Errno::EPIPE,
|
27
|
+
Errno::EINVAL
|
28
|
+
]
|
29
|
+
|
30
|
+
# @params [Hash] options
|
31
|
+
#
|
32
|
+
# @option options [Numeric] :idle_timeout (60) The number of seconds a
|
33
|
+
# connection is allowed to sit idle before it is closed and removed
|
34
|
+
# from the pool.
|
35
|
+
#
|
36
|
+
# @option options [Numeric] :open_timeout (15) The number of seconds to
|
37
|
+
# wait when opening a http session before raising a timeout exception.
|
38
|
+
#
|
39
|
+
def initialize options = {}
|
40
|
+
@pool = []
|
41
|
+
@pool_mutex = Mutex.new
|
42
|
+
@open_timeout = options[:open_timeout] || 15
|
43
|
+
@idle_timeout = options[:idle_timeout] || 60
|
44
|
+
end
|
45
|
+
|
46
|
+
# @return [Integer]
|
47
|
+
attr_reader :idle_timeout
|
48
|
+
|
49
|
+
# @return [Integer]
|
50
|
+
attr_accessor :open_timeout
|
51
|
+
|
52
|
+
# Requests a http session from the connection pool.
|
53
|
+
#
|
54
|
+
# pool.connection_for('domain.com') do |connection|
|
55
|
+
#
|
56
|
+
# # make
|
57
|
+
# connection.request(Net::HTTP::Get.new('/index.html'))
|
58
|
+
# connection.request(Net::HTTP::Get.new('/about.html'))
|
59
|
+
#
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# The yielded connection object is a thin wrapper around the persistent
|
63
|
+
# http session object. You generally want to call {Connection#request}
|
64
|
+
# on the yielded object. When the block is complete the connection
|
65
|
+
# will be returned to the pool.
|
66
|
+
#
|
67
|
+
# @param [String] host
|
68
|
+
#
|
69
|
+
# @param [Hash] options
|
70
|
+
#
|
71
|
+
# @option options [Integer] :port Which port the connection should use.
|
72
|
+
# Defaults to 80, unless +:ssl+ is +true+, then it defaults to 443.
|
73
|
+
#
|
74
|
+
# @option options [Boolean] :ssl If the connection should be made over
|
75
|
+
# SSL. Defaults to +false+, unless +:port+ is 443, then it defaults
|
76
|
+
# to +true+.
|
77
|
+
#
|
78
|
+
# @option options [Boolean] :ssl_verify_peer (true) If true, ssl
|
79
|
+
# connections will verify peer certificates. This should only ever be
|
80
|
+
# set false false for debugging purposes.
|
81
|
+
#
|
82
|
+
# @option options [String] :ssl_ca_file Full path to the SSL certificate
|
83
|
+
# authority bundle file that should be used when verifying peer
|
84
|
+
# certificates. If you do not pass +:ssl_ca_file+ or +:ssl_ca_path+
|
85
|
+
# the the system default will be used if available.
|
86
|
+
#
|
87
|
+
# @option options [String] :ssl_ca_path Full path of the directory that
|
88
|
+
# contains the unbundled SSL certificate authority files for verifying
|
89
|
+
# peer certificates. If you do not pass +:ssl_ca_file+ or +:ssl_ca_path+
|
90
|
+
# the the system default will be used if available.
|
91
|
+
#
|
92
|
+
# @option options [URI::HTTP,String] :proxy_uri (nil) A URI string or
|
93
|
+
# URI::HTTP for a proxy reqeusts should be made through. You should
|
94
|
+
# not pass both +:proxy_uri+ with any of the other proxy options.
|
95
|
+
#
|
96
|
+
# :proxy_uri => 'http://user:pass@host.com:80'
|
97
|
+
#
|
98
|
+
# @option options [String] :proxy_address
|
99
|
+
#
|
100
|
+
# @option options [String] :proxy_port
|
101
|
+
#
|
102
|
+
# @option options [String] :proxy_user
|
103
|
+
#
|
104
|
+
# @option options [String] :proxy_password
|
105
|
+
#
|
106
|
+
# @yieldparam [Connection] connection
|
107
|
+
#
|
108
|
+
# @return [nil]
|
109
|
+
#
|
110
|
+
def connection_for host, options = {}, &block
|
111
|
+
connection = Connection.new(self, host, options)
|
112
|
+
if block_given?
|
113
|
+
yield(connection)
|
114
|
+
else
|
115
|
+
connection
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def request connection, *request_args, &block
|
120
|
+
session = nil
|
121
|
+
response = nil
|
122
|
+
retried = false
|
123
|
+
begin
|
124
|
+
session = session_for(connection)
|
125
|
+
session.http_session.read_timeout = connection.read_timeout
|
126
|
+
response = session.request(*request_args, &block)
|
127
|
+
rescue *SOCKET_ERRORS => error
|
128
|
+
# retry socket errors once
|
129
|
+
unless retried
|
130
|
+
retried = true
|
131
|
+
retry
|
132
|
+
end
|
133
|
+
raise error
|
134
|
+
else
|
135
|
+
@pool_mutex.synchronize { @pool << session }
|
136
|
+
end
|
137
|
+
response
|
138
|
+
end
|
139
|
+
|
140
|
+
# Returns the number of sessions currently in the pool, not counting those
|
141
|
+
# currently in use.
|
142
|
+
def size
|
143
|
+
@pool_mutex.synchronize { @pool.size }
|
144
|
+
end
|
145
|
+
|
146
|
+
# Removes http sessions from the pool that have passed the idle timeout
|
147
|
+
def clean!
|
148
|
+
@pool_mutex.synchronize { _clean }
|
149
|
+
end
|
150
|
+
|
151
|
+
# Finishes and removes removes all sessions from the pool.
|
152
|
+
# If empty! is called while there are outstanding requests they may
|
153
|
+
# get checked back into the pool, leaving the pool in a non-empty state.
|
154
|
+
def empty!
|
155
|
+
@pool_mutex.synchronize do
|
156
|
+
@pool.each(&:finish)
|
157
|
+
@pool = []
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
# Returns a suitable session from the pool or creates a new one
|
162
|
+
private
|
163
|
+
def session_for connection
|
164
|
+
session = nil
|
165
|
+
|
166
|
+
@pool_mutex.synchronize do
|
167
|
+
_clean
|
168
|
+
session = @pool.find{|idle_session| idle_session.key == connection.key }
|
169
|
+
@pool.delete(session) if session
|
170
|
+
end
|
171
|
+
|
172
|
+
if session.nil?
|
173
|
+
session = Session.for(connection, open_timeout)
|
174
|
+
end
|
175
|
+
|
176
|
+
session
|
177
|
+
end
|
178
|
+
|
179
|
+
private
|
180
|
+
def _clean
|
181
|
+
now = Time.now
|
182
|
+
@pool.delete_if do |idle_session|
|
183
|
+
if
|
184
|
+
idle_session.last_used_at.nil? or
|
185
|
+
now - idle_session.last_used_at > idle_timeout
|
186
|
+
then
|
187
|
+
idle_session.finish
|
188
|
+
true
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
# Copyright 2011 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
|
+
require 'uri'
|
15
|
+
|
16
|
+
class Net::HTTP::ConnectionPool
|
17
|
+
|
18
|
+
# A light wrapper around Net::HTTP.
|
19
|
+
#
|
20
|
+
# You should not need to construct connection objects yourself.
|
21
|
+
# You receive them as a response to {ConnectionPool#connection_for}.
|
22
|
+
#
|
23
|
+
class Connection
|
24
|
+
|
25
|
+
# @param [ConnectionPool] pool
|
26
|
+
# @param (see ConnectionPool#connection_for)
|
27
|
+
# @option (see ConnectionPool#connection_for)
|
28
|
+
# @return [Connection]
|
29
|
+
def initialize pool, host, options = {}
|
30
|
+
|
31
|
+
@pool = pool
|
32
|
+
|
33
|
+
@host = host
|
34
|
+
|
35
|
+
@port = options.key?(:port) ? options[:port] : (options[:ssl] ? 443 : 80)
|
36
|
+
|
37
|
+
@ssl = options.key?(:ssl) ? options[:ssl] : (port == 443)
|
38
|
+
|
39
|
+
@ssl_verify_peer = options.key?(:ssl_verify_peer) ?
|
40
|
+
options[:ssl_verify_peer] : true
|
41
|
+
|
42
|
+
@ssl_ca_file = options[:ssl_ca_file]
|
43
|
+
|
44
|
+
@ssl_ca_path = options[:ssl_ca_path]
|
45
|
+
|
46
|
+
if uri = options[:proxy_uri]
|
47
|
+
uri = URI.parse(uri) if uri.is_a?(String)
|
48
|
+
@proxy_address = uri.host
|
49
|
+
@proxy_port = uri.port
|
50
|
+
@proxy_user = uri.user
|
51
|
+
@proxy_password = uri.password
|
52
|
+
else
|
53
|
+
@proxy_address = options[:proxy_address]
|
54
|
+
@proxy_port = options[:proxy_port]
|
55
|
+
@proxy_user = options[:proxy_user]
|
56
|
+
@proxy_password = options[:proxy_password]
|
57
|
+
end
|
58
|
+
|
59
|
+
@read_timeout = options[:read_timeout] || 60
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [ConnectionPool]
|
64
|
+
attr_reader :pool
|
65
|
+
|
66
|
+
# @return [String]
|
67
|
+
attr_reader :host
|
68
|
+
|
69
|
+
# @return [Integer]
|
70
|
+
attr_reader :port
|
71
|
+
|
72
|
+
# @return [Boolean]
|
73
|
+
attr_reader :ssl
|
74
|
+
|
75
|
+
# @return [Boolean]
|
76
|
+
attr_reader :ssl_verify_peer
|
77
|
+
|
78
|
+
# @return [String,nil]
|
79
|
+
attr_reader :ssl_ca_file
|
80
|
+
|
81
|
+
# @return [String,nil]
|
82
|
+
attr_reader :ssl_ca_path
|
83
|
+
|
84
|
+
# @return [String,nil]
|
85
|
+
attr_reader :proxy_address
|
86
|
+
|
87
|
+
# @return [Integer,nil]
|
88
|
+
attr_reader :proxy_port
|
89
|
+
|
90
|
+
# @return [String,nil]
|
91
|
+
attr_reader :proxy_user
|
92
|
+
|
93
|
+
# @return [String,nil]
|
94
|
+
attr_reader :proxy_password
|
95
|
+
|
96
|
+
# @return [Numeric,nil]
|
97
|
+
attr_accessor :read_timeout
|
98
|
+
|
99
|
+
# @return [Boolean] Returns true if this connection requires SSL.
|
100
|
+
def ssl?
|
101
|
+
@ssl
|
102
|
+
end
|
103
|
+
|
104
|
+
# @return [Boolean] Returns true if ssl connections should verify the
|
105
|
+
# peer certificate.
|
106
|
+
def ssl_verify_peer?
|
107
|
+
@ssl_verify_peer
|
108
|
+
end
|
109
|
+
|
110
|
+
# @return [Boolean] Returns true if this connection proxies requests.
|
111
|
+
def proxy?
|
112
|
+
!!proxy_address
|
113
|
+
end
|
114
|
+
|
115
|
+
def request *args, &block
|
116
|
+
pool.request(self, *args, &block)
|
117
|
+
end
|
118
|
+
|
119
|
+
# @return [String] Returns a key that can be used to group connections
|
120
|
+
# that connection to the same host.
|
121
|
+
def key
|
122
|
+
@key ||= begin
|
123
|
+
%w(
|
124
|
+
host port
|
125
|
+
ssl ssl_verify_peer ssl_ca_file ssl_ca_path
|
126
|
+
proxy_address proxy_port proxy_user proxy_password
|
127
|
+
).map{|part| send(part).to_s }.join(":")
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|