aws-s3 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/INSTALL +9 -3
- data/README +2 -2
- data/Rakefile +9 -1
- data/bin/s3sh +5 -3
- data/lib/aws/s3/base.rb +1 -1
- data/lib/aws/s3/bucket.rb +6 -2
- data/lib/aws/s3/connection.rb +10 -11
- data/lib/aws/s3/exceptions.rb +1 -1
- data/lib/aws/s3/extensions.rb +52 -13
- data/lib/aws/s3/object.rb +9 -2
- data/lib/aws/s3/parsing.rb +5 -3
- data/lib/aws/s3/service.rb +9 -1
- data/lib/aws/s3/version.rb +1 -1
- data/test/base_test.rb +1 -1
- data/test/bucket_test.rb +1 -1
- data/test/extensions_test.rb +0 -5
- data/test/object_test.rb +9 -0
- data/test/parsing_test.rb +4 -0
- data/test/remote/bucket_test.rb +20 -1
- data/test/remote/object_test.rb +63 -34
- metadata +2 -2
data/INSTALL
CHANGED
@@ -26,9 +26,15 @@ Then add the following line, save and exit:
|
|
26
26
|
|
27
27
|
aws svn://rubyforge.org/var/svn/amazon/s3/trunk
|
28
28
|
|
29
|
+
If you go the svn route, be sure that you have all the dependencies installed. The list of dependencies follow.
|
30
|
+
|
29
31
|
== Dependencies
|
30
32
|
|
31
|
-
|
33
|
+
sudo gem i xml-simple -ry
|
34
|
+
sudo gem i builder -ry
|
35
|
+
sudo gem i mime-types -ry
|
36
|
+
|
37
|
+
=== XML parsing (xml-simple)
|
32
38
|
|
33
39
|
AWS::S3 depends on XmlSimple (http://xml-simple.rubyforge.org/). When installing aws/s3 with
|
34
40
|
Rubygems, this dependency will be taken care of for you. Otherwise, installation instructions are listed on the xml-simple
|
@@ -36,10 +42,10 @@ site.
|
|
36
42
|
|
37
43
|
If your system has the Ruby libxml bindings installed (http://libxml.rubyforge.org/) they will be used instead of REXML (which is what XmlSimple uses). For those concerned with speed and efficiency, it would behoove you to install libxml (instructions here: http://libxml.rubyforge.org/install.html) as it is considerably faster and less expensive than REXML.
|
38
44
|
|
39
|
-
=== XML generation
|
45
|
+
=== XML generation (builder)
|
40
46
|
|
41
47
|
AWS::S3 also depends on the Builder library (http://builder.rubyforge.org/ and http://rubyforge.org/projects/builder/). This will also automatically be installed for you when using Rubygems.
|
42
48
|
|
43
|
-
=== Content type inference
|
49
|
+
=== Content type inference (mime-types)
|
44
50
|
|
45
51
|
AWS::S3 depends on the MIME::Types library (http://mime-types.rubyforge.org/) to infer the content type of an object that does not explicitly specify it. This library will automatically be installed for you when using Rubygems.
|
data/README
CHANGED
@@ -135,7 +135,7 @@ You can store an object on S3 by specifying a key, its data and the name of the
|
|
135
135
|
'photos'
|
136
136
|
)
|
137
137
|
|
138
|
-
The content type of the object will be
|
138
|
+
The content type of the object will be inferred by its extension. If the appropriate content type can not be inferred, S3 defaults
|
139
139
|
to <tt>binary/octect-stream</tt>.
|
140
140
|
|
141
141
|
If you want to override this, you can explicitly indicate what content type the object should have with the <tt>:content_type</tt> option:
|
@@ -279,7 +279,7 @@ This time we didn't have to explicitly pass in the bucket name, as the JukeBoxSo
|
|
279
279
|
always use the 'jukebox' bucket.
|
280
280
|
|
281
281
|
"Astute readers", as they say, may have noticed that we used the third parameter to pass in the content type,
|
282
|
-
rather than the fourth parameter as we had the last time we created an object. If the bucket can be
|
282
|
+
rather than the fourth parameter as we had the last time we created an object. If the bucket can be inferred, or
|
283
283
|
is explicitly set, as we've done in the JukeBoxSong class, then the third argument can be used to pass in
|
284
284
|
options.
|
285
285
|
|
data/Rakefile
CHANGED
@@ -129,10 +129,12 @@ namespace :dist do
|
|
129
129
|
sh %(svn ci CHANGELOG -m "Bump changelog version marker for release")
|
130
130
|
end
|
131
131
|
|
132
|
+
package_name = lambda {|specification| File.join('pkg', "#{specification.name}-#{specification.version}")}
|
133
|
+
|
132
134
|
desc 'Push a release to rubyforge'
|
133
135
|
task :release => [:confirm_release, :clean, :add_release_marker_to_changelog, :package, :commit_changelog, :tag] do
|
134
136
|
require 'rubyforge'
|
135
|
-
package =
|
137
|
+
package = package_name[spec]
|
136
138
|
|
137
139
|
rubyforge = RubyForge.new
|
138
140
|
rubyforge.login
|
@@ -151,6 +153,12 @@ namespace :dist do
|
|
151
153
|
end
|
152
154
|
end
|
153
155
|
|
156
|
+
desc 'Upload a beta gem'
|
157
|
+
task :push_beta_gem => [:clobber_package, :package] do
|
158
|
+
beta_gem = package_name[spec]
|
159
|
+
sh %(scp #{beta_gem}.gem marcel@rubyforge.org:/var/www/gforge-projects/amazon/beta)
|
160
|
+
end
|
161
|
+
|
154
162
|
task :spec do
|
155
163
|
puts spec.to_ruby
|
156
164
|
end
|
data/bin/s3sh
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
s3_lib
|
3
|
-
setup
|
4
|
-
|
2
|
+
s3_lib = File.dirname(__FILE__) + '/../lib/aws/s3'
|
3
|
+
setup = File.dirname(__FILE__) + '/setup'
|
4
|
+
irb_name = RUBY_PLATFORM =~ /mswin32/ ? 'irb.bat' : 'irb'
|
5
|
+
|
6
|
+
exec "#{irb_name} -r #{s3_lib} -r #{setup} --simple-prompt"
|
data/lib/aws/s3/base.rb
CHANGED
@@ -121,7 +121,7 @@ module AWS #:nodoc:
|
|
121
121
|
# always use the 'jukebox' bucket.
|
122
122
|
#
|
123
123
|
# "Astute readers", as they say, may have noticed that we used the third parameter to pass in the content type,
|
124
|
-
# rather than the fourth parameter as we had the last time we created an object. If the bucket can be
|
124
|
+
# rather than the fourth parameter as we had the last time we created an object. If the bucket can be inferred, or
|
125
125
|
# is explicitly set, as we've done in the JukeBoxSong class, then the third argument can be used to pass in
|
126
126
|
# options.
|
127
127
|
#
|
data/lib/aws/s3/bucket.rb
CHANGED
@@ -175,10 +175,14 @@ module AWS
|
|
175
175
|
|
176
176
|
private
|
177
177
|
def validate_name!(name)
|
178
|
-
raise InvalidBucketName.new(name) unless name =~ /^[-\w]{3,255}$/
|
178
|
+
raise InvalidBucketName.new(name) unless name =~ /^[-\w.]{3,255}$/
|
179
179
|
end
|
180
180
|
|
181
181
|
def path(name, options = {})
|
182
|
+
if name.is_a?(Hash)
|
183
|
+
options = name
|
184
|
+
name = nil
|
185
|
+
end
|
182
186
|
"/#{bucket_name(name)}#{RequestOptions.process(options).to_query_string}"
|
183
187
|
end
|
184
188
|
end
|
@@ -279,7 +283,7 @@ module AWS
|
|
279
283
|
end
|
280
284
|
alias_method :clear, :delete_all
|
281
285
|
|
282
|
-
# Buckets
|
286
|
+
# Buckets observe their objects and have this method called when one of their objects
|
283
287
|
# is either stored or deleted.
|
284
288
|
def update(action, object) #:nodoc:
|
285
289
|
case action
|
data/lib/aws/s3/connection.rb
CHANGED
@@ -22,12 +22,14 @@ module AWS
|
|
22
22
|
http.start do
|
23
23
|
request = request_method(verb).new(path, headers)
|
24
24
|
authenticate!(request)
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
if body
|
26
|
+
if body.respond_to?(:read)
|
27
|
+
request.body_stream = body
|
28
|
+
request.content_length = body.respond_to?(:lstat) ? body.lstat.size : body.size
|
29
|
+
else
|
30
|
+
request.body = body
|
31
|
+
end
|
32
|
+
end
|
31
33
|
http.request(request, &block)
|
32
34
|
end
|
33
35
|
end
|
@@ -82,7 +84,8 @@ module AWS
|
|
82
84
|
|
83
85
|
module Management #:nodoc:
|
84
86
|
def self.included(base)
|
85
|
-
base.
|
87
|
+
base.cattr_accessor :connections
|
88
|
+
base.connections = {}
|
86
89
|
base.extend ClassMethods
|
87
90
|
end
|
88
91
|
|
@@ -154,10 +157,6 @@ module AWS
|
|
154
157
|
end
|
155
158
|
|
156
159
|
private
|
157
|
-
def connections
|
158
|
-
class_variable_get(:@@connections)
|
159
|
-
end
|
160
|
-
|
161
160
|
def connection_name
|
162
161
|
name
|
163
162
|
end
|
data/lib/aws/s3/exceptions.rb
CHANGED
@@ -88,7 +88,7 @@ module AWS
|
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
91
|
-
# Raised if the current bucket can not be
|
91
|
+
# Raised if the current bucket can not be inferred when not explicitly specifying the target bucket in the calling
|
92
92
|
# method's arguments.
|
93
93
|
class CurrentBucketNotSpecified < S3Exception
|
94
94
|
def initialize(address)
|
data/lib/aws/s3/extensions.rb
CHANGED
@@ -6,7 +6,7 @@ class Hash
|
|
6
6
|
query_string = ''
|
7
7
|
query_string << '?' if include_question_mark
|
8
8
|
query_string << inject([]) do |parameters, (key, value)|
|
9
|
-
parameters << [key, value].map {|element|
|
9
|
+
parameters << [key, value].map {|element| element.to_s}.join('=')
|
10
10
|
end.join('&')
|
11
11
|
end
|
12
12
|
|
@@ -123,21 +123,60 @@ class Module
|
|
123
123
|
alias_method :const_missing, :const_missing_from_s3_library
|
124
124
|
end
|
125
125
|
|
126
|
+
|
127
|
+
class Class # :nodoc:
|
128
|
+
def cattr_reader(*syms)
|
129
|
+
syms.flatten.each do |sym|
|
130
|
+
class_eval(<<-EOS, __FILE__, __LINE__)
|
131
|
+
unless defined? @@#{sym}
|
132
|
+
@@#{sym} = nil
|
133
|
+
end
|
134
|
+
|
135
|
+
def self.#{sym}
|
136
|
+
@@#{sym}
|
137
|
+
end
|
138
|
+
|
139
|
+
def #{sym}
|
140
|
+
@@#{sym}
|
141
|
+
end
|
142
|
+
EOS
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def cattr_writer(*syms)
|
147
|
+
syms.flatten.each do |sym|
|
148
|
+
class_eval(<<-EOS, __FILE__, __LINE__)
|
149
|
+
unless defined? @@#{sym}
|
150
|
+
@@#{sym} = nil
|
151
|
+
end
|
152
|
+
|
153
|
+
def self.#{sym}=(obj)
|
154
|
+
@@#{sym} = obj
|
155
|
+
end
|
156
|
+
|
157
|
+
def #{sym}=(obj)
|
158
|
+
@@#{sym} = obj
|
159
|
+
end
|
160
|
+
EOS
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def cattr_accessor(*syms)
|
165
|
+
cattr_reader(*syms)
|
166
|
+
cattr_writer(*syms)
|
167
|
+
end
|
168
|
+
end if Class.instance_methods(false).grep(/^cattr_(?:reader|writer|accessor)$/).empty?
|
169
|
+
|
126
170
|
module SelectiveAttributeProxy
|
127
171
|
def self.included(klass)
|
128
172
|
klass.extend(ClassMethods)
|
129
173
|
klass.class_eval(<<-EVAL, __FILE__, __LINE__)
|
130
|
-
|
131
|
-
|
132
|
-
@@attribute_proxy_options = {:exclusively => true}
|
133
|
-
|
134
|
-
def self.attribute_proxy
|
135
|
-
@@attribute_proxy
|
136
|
-
end
|
174
|
+
cattr_accessor :attribute_proxy
|
175
|
+
cattr_accessor :attribute_proxy_options
|
137
176
|
|
138
|
-
|
139
|
-
|
140
|
-
|
177
|
+
# Default name for attribute storage
|
178
|
+
self.attribute_proxy = :attributes
|
179
|
+
self.attribute_proxy_options = {:exclusively => true}
|
141
180
|
|
142
181
|
private
|
143
182
|
# By default proxy all attributes
|
@@ -168,9 +207,9 @@ module SelectiveAttributeProxy
|
|
168
207
|
if attribute_name.is_a?(Hash)
|
169
208
|
options = attribute_name
|
170
209
|
else
|
171
|
-
|
210
|
+
self.attribute_proxy = attribute_name
|
172
211
|
end
|
173
|
-
|
212
|
+
self.attribute_proxy_options = options
|
174
213
|
end
|
175
214
|
end
|
176
215
|
end
|
data/lib/aws/s3/object.rb
CHANGED
@@ -11,7 +11,7 @@ module AWS
|
|
11
11
|
# 'photos'
|
12
12
|
# )
|
13
13
|
#
|
14
|
-
# The content type of the object will be
|
14
|
+
# The content type of the object will be inferred by its extension. If the appropriate content type can not be inferred, S3 defaults
|
15
15
|
# to <tt>binary/octect-stream</tt>.
|
16
16
|
#
|
17
17
|
# If you want to override this, you can explicitly indicate what content type the object should have with the <tt>:content_type</tt> option:
|
@@ -191,8 +191,15 @@ module AWS
|
|
191
191
|
|
192
192
|
# Fetch information about the key with <tt>name</tt> from <tt>bucket</tt>. Information includes content type, content length,
|
193
193
|
# last modified time, and others.
|
194
|
+
#
|
195
|
+
# If the specified key does not exist, NoSuchKey is raised.
|
194
196
|
def about(key, bucket = nil, options = {})
|
195
|
-
|
197
|
+
response = head(path!(bucket, key, options), options)
|
198
|
+
if response.client_error?
|
199
|
+
raise NoSuchKey.new("No such key `#{key}'", bucket)
|
200
|
+
else
|
201
|
+
About.new(response.headers)
|
202
|
+
end
|
196
203
|
end
|
197
204
|
|
198
205
|
# Delete object with <tt>key</tt> from <tt>bucket</tt>.
|
data/lib/aws/s3/parsing.rb
CHANGED
data/lib/aws/s3/service.rb
CHANGED
@@ -8,7 +8,15 @@ module AWS
|
|
8
8
|
@@response = nil #:nodoc:
|
9
9
|
|
10
10
|
class << self
|
11
|
-
# List all your buckets
|
11
|
+
# List all your buckets.
|
12
|
+
#
|
13
|
+
# Service.buckets
|
14
|
+
# # => []
|
15
|
+
#
|
16
|
+
# For performance reasons, the bucket list will be cached. If you want avoid all caching, pass the <tt>:reload</tt>
|
17
|
+
# as an argument:
|
18
|
+
#
|
19
|
+
# Service.buckets(:reload)
|
12
20
|
def buckets
|
13
21
|
response = get('/')
|
14
22
|
if response.empty?
|
data/lib/aws/s3/version.rb
CHANGED
data/test/base_test.rb
CHANGED
data/test/bucket_test.rb
CHANGED
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/test_helper'
|
|
2
2
|
|
3
3
|
class BucketTest < Test::Unit::TestCase
|
4
4
|
def test_bucket_name_validation
|
5
|
-
valid_names = %w(123 joe step-one step_two step3 step_4 step-5)
|
5
|
+
valid_names = %w(123 joe step-one step_two step3 step_4 step-5 step.six)
|
6
6
|
invalid_names = ['12', 'jo', 'kevin spacey', 'larry@wall', '', 'a' * 256]
|
7
7
|
validate_name = Proc.new {|name| Bucket.send(:validate_name!, name)}
|
8
8
|
valid_names.each do |valid_name|
|
data/test/extensions_test.rb
CHANGED
@@ -27,11 +27,6 @@ class HashExtensionsTest < Test::Unit::TestCase
|
|
27
27
|
assert qs['one=1&two=2'] || qs['two=2&one=1']
|
28
28
|
end
|
29
29
|
|
30
|
-
def test_keys_and_values_are_url_encoded
|
31
|
-
hash = {'key with spaces' => 'value with spaces'}
|
32
|
-
assert_equal '?key+with+spaces=value+with+spaces', hash.to_query_string
|
33
|
-
end
|
34
|
-
|
35
30
|
def test_normalized_options
|
36
31
|
expectations = [
|
37
32
|
[{:foo_bar => 1}, {'foo-bar' => '1'}],
|
data/test/object_test.rb
CHANGED
@@ -136,6 +136,15 @@ class ObjectTest < Test::Unit::TestCase
|
|
136
136
|
assert_equal 'f21f7c4e8ea6e34b268887b07d6da745', file.etag
|
137
137
|
end
|
138
138
|
end
|
139
|
+
|
140
|
+
def test_fetching_information_about_an_object_that_does_not_exist_raises_no_such_key
|
141
|
+
S3Object.in_test_mode do
|
142
|
+
S3Object.request_returns :body => '', :code => 404
|
143
|
+
assert_raises(NoSuchKey) do
|
144
|
+
S3Object.about('asdfasdfasdfas-this-does-not-exist', 'bucket does not matter')
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
139
148
|
end
|
140
149
|
|
141
150
|
class MetadataTest < Test::Unit::TestCase
|
data/test/parsing_test.rb
CHANGED
@@ -79,4 +79,8 @@ class XmlParserTest < Test::Unit::TestCase
|
|
79
79
|
policy = Parsing::XmlParser.new(Fixtures::Policies.policy_with_one_grant)
|
80
80
|
assert_kind_of Array, policy['access_control_list']['grant']
|
81
81
|
end
|
82
|
+
|
83
|
+
def test_empty_xml_response_is_not_parsed
|
84
|
+
assert_equal({}, Parsing::XmlParser.new(''))
|
85
|
+
end
|
82
86
|
end
|
data/test/remote/bucket_test.rb
CHANGED
@@ -123,5 +123,24 @@ class RemoteBucketTest < Test::Unit::TestCase
|
|
123
123
|
|
124
124
|
assert bucket.empty?
|
125
125
|
end
|
126
|
-
|
126
|
+
|
127
|
+
def test_bucket_name_is_switched_with_options_when_bucket_is_implicit_and_options_are_passed
|
128
|
+
Object.const_set(:ImplicitlyNamedBucket, Class.new(Bucket))
|
129
|
+
ImplicitlyNamedBucket.current_bucket = TEST_BUCKET
|
130
|
+
assert ImplicitlyNamedBucket.objects.empty?
|
131
|
+
|
132
|
+
%w(a b c).each {|key| S3Object.store(key, 'value does not matter', TEST_BUCKET)}
|
133
|
+
|
134
|
+
assert_equal 3, ImplicitlyNamedBucket.objects.size
|
135
|
+
|
136
|
+
objects = nil
|
137
|
+
assert_nothing_raised do
|
138
|
+
objects = ImplicitlyNamedBucket.objects(:max_keys => 1)
|
139
|
+
end
|
140
|
+
|
141
|
+
assert objects
|
142
|
+
assert_equal 1, objects.size
|
143
|
+
ensure
|
144
|
+
%w(a b c).each {|key| S3Object.delete(key, TEST_BUCKET)}
|
145
|
+
end
|
127
146
|
end
|
data/test/remote/object_test.rb
CHANGED
@@ -13,7 +13,6 @@ class RemoteS3ObjectTest < Test::Unit::TestCase
|
|
13
13
|
key = 'testing_s3objects'
|
14
14
|
value = 'testing'
|
15
15
|
content_type = 'text/plain'
|
16
|
-
fetch_object_at = Proc.new {|url| Net::HTTP.get_response(URI.parse(url))}
|
17
16
|
unauthenticated_url = ['http:/', Base.connection.http.address, TEST_BUCKET, key].join('/')
|
18
17
|
|
19
18
|
# Create an object
|
@@ -103,7 +102,7 @@ class RemoteS3ObjectTest < Test::Unit::TestCase
|
|
103
102
|
|
104
103
|
# Test that it is publicly readable
|
105
104
|
|
106
|
-
response = fetch_object_at
|
105
|
+
response = fetch_object_at(unauthenticated_url)
|
107
106
|
assert (200..299).include?(response.code.to_i)
|
108
107
|
|
109
108
|
# Confirm that it has no meta data
|
@@ -151,12 +150,12 @@ class RemoteS3ObjectTest < Test::Unit::TestCase
|
|
151
150
|
|
152
151
|
# Confirm object is no longer publicly readable
|
153
152
|
|
154
|
-
response = fetch_object_at
|
153
|
+
response = fetch_object_at(unauthenticated_url)
|
155
154
|
assert (400..499).include?(response.code.to_i)
|
156
155
|
|
157
156
|
# Confirm object is accessible from its authenticated url
|
158
157
|
|
159
|
-
response = fetch_object_at
|
158
|
+
response = fetch_object_at(object.url)
|
160
159
|
assert (200..299).include?(response.code.to_i)
|
161
160
|
|
162
161
|
# Copy the object
|
@@ -234,39 +233,10 @@ class RemoteS3ObjectTest < Test::Unit::TestCase
|
|
234
233
|
end
|
235
234
|
|
236
235
|
assert result
|
237
|
-
|
238
|
-
# Confirm we can create an object with spaces in its key
|
239
|
-
|
240
|
-
object = S3Object.new(:value => 'just some text')
|
241
|
-
object.key = 'name with spaces'
|
242
|
-
object.bucket = Bucket.find(TEST_BUCKET)
|
243
|
-
|
244
|
-
assert_nothing_raised do
|
245
|
-
object.store
|
246
|
-
end
|
247
|
-
|
248
|
-
object = nil
|
249
|
-
assert_nothing_raised do
|
250
|
-
object = S3Object.find('name with spaces', TEST_BUCKET)
|
251
|
-
end
|
252
|
-
|
253
|
-
assert object
|
254
|
-
assert_equal 'name with spaces', object.key
|
255
|
-
|
256
|
-
# Confirm authenticated url is generated correctly despite space in file name
|
257
|
-
|
258
|
-
response = fetch_object_at[object.url]
|
259
|
-
assert (200..299).include?(response.code.to_i)
|
260
|
-
|
261
|
-
# Confirm we can delete objects with spaces in their key
|
262
|
-
|
263
|
-
assert_nothing_raised do
|
264
|
-
object.delete
|
265
|
-
end
|
266
236
|
end
|
267
237
|
|
268
238
|
def test_content_type_inference
|
269
|
-
# Confirm appropriate content type is
|
239
|
+
# Confirm appropriate content type is inferred when not specified
|
270
240
|
|
271
241
|
content_type_objects = {'foo.jpg' => 'image/jpeg', 'no-extension-specified' => 'binary/octet-stream', 'foo.txt' => 'text/plain'}
|
272
242
|
content_type_objects.each_key do |key|
|
@@ -291,4 +261,63 @@ class RemoteS3ObjectTest < Test::Unit::TestCase
|
|
291
261
|
# Get rid of objects we just created
|
292
262
|
content_type_objects.each_key {|key| S3Object.delete(key, TEST_BUCKET) }
|
293
263
|
end
|
264
|
+
|
265
|
+
def test_body_can_be_more_than_just_string_or_io
|
266
|
+
require 'stringio'
|
267
|
+
key = 'testing-body-as-string-io'
|
268
|
+
io = StringIO.new('hello there')
|
269
|
+
S3Object.store(key, io, TEST_BUCKET)
|
270
|
+
assert_equal 'hello there', S3Object.value(key, TEST_BUCKET)
|
271
|
+
ensure
|
272
|
+
S3Object.delete(key, TEST_BUCKET)
|
273
|
+
end
|
274
|
+
|
275
|
+
def test_fetching_information_about_an_object_that_does_not_exist_raises_no_such_key
|
276
|
+
assert_raises(NoSuchKey) do
|
277
|
+
S3Object.about('asdfasdfasdfas-this-does-not-exist', TEST_BUCKET)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
# Regression test for http://developer.amazonwebservices.com/connect/thread.jspa?messageID=49152&tstart=0#49152
|
282
|
+
def test_finding_an_object_with_slashes_in_its_name_does_not_escape_the_slash
|
283
|
+
S3Object.store('rails/1', 'value does not matter', TEST_BUCKET)
|
284
|
+
S3Object.store('rails/1.html', 'value does not matter', TEST_BUCKET)
|
285
|
+
|
286
|
+
object = nil
|
287
|
+
assert_nothing_raised do
|
288
|
+
object = S3Object.find('rails/1.html', TEST_BUCKET)
|
289
|
+
end
|
290
|
+
|
291
|
+
assert_equal 'rails/1.html', object.key
|
292
|
+
ensure
|
293
|
+
%w(rails/1 rails/1.html).each {|key| S3Object.delete(key, TEST_BUCKET)}
|
294
|
+
end
|
295
|
+
|
296
|
+
def test_finding_an_object_with_spaces_in_its_name
|
297
|
+
assert_nothing_raised do
|
298
|
+
S3Object.store('name with spaces', 'value does not matter', TEST_BUCKET)
|
299
|
+
end
|
300
|
+
|
301
|
+
object = nil
|
302
|
+
assert_nothing_raised do
|
303
|
+
object = S3Object.find('name with spaces', TEST_BUCKET)
|
304
|
+
end
|
305
|
+
|
306
|
+
assert object
|
307
|
+
assert_equal 'name with spaces', object.key
|
308
|
+
|
309
|
+
# Confirm authenticated url is generated correctly despite space in file name
|
310
|
+
|
311
|
+
response = fetch_object_at(object.url)
|
312
|
+
assert (200..299).include?(response.code.to_i)
|
313
|
+
|
314
|
+
ensure
|
315
|
+
S3Object.delete('name with spaces', TEST_BUCKET)
|
316
|
+
end
|
317
|
+
|
318
|
+
private
|
319
|
+
def fetch_object_at(url)
|
320
|
+
Net::HTTP.get_response(URI.parse(url))
|
321
|
+
end
|
322
|
+
|
294
323
|
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
|
|
3
3
|
specification_version: 1
|
4
4
|
name: aws-s3
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.2.
|
7
|
-
date: 2006-
|
6
|
+
version: 0.2.1
|
7
|
+
date: 2006-12-04 00:00:00 -06:00
|
8
8
|
summary: Client library for Amazon's Simple Storage Service's REST API
|
9
9
|
require_paths:
|
10
10
|
- lib
|