s3 0.3.0 → 0.3.1
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/.gitignore +7 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +27 -0
- data/Rakefile +20 -0
- data/lib/s3/connection.rb +9 -2
- data/lib/s3/object.rb +1 -1
- data/lib/s3/service.rb +6 -2
- data/lib/s3/version.rb +1 -1
- data/s3.gemspec +27 -0
- data/test/bucket_test.rb +215 -0
- data/test/connection_test.rb +210 -0
- data/test/object_test.rb +161 -0
- data/test/service_test.rb +111 -0
- data/test/signature_test.rb +143 -0
- data/test/test_helper.rb +7 -0
- metadata +40 -20
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
s3 (0.3.1)
|
5
|
+
proxies
|
6
|
+
trollop
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
mocha (0.9.8)
|
12
|
+
rake
|
13
|
+
proxies (0.1.1)
|
14
|
+
rake (0.8.7)
|
15
|
+
test-unit (2.1.1)
|
16
|
+
trollop (1.16.2)
|
17
|
+
|
18
|
+
PLATFORMS
|
19
|
+
ruby
|
20
|
+
|
21
|
+
DEPENDENCIES
|
22
|
+
bundler (>= 1.0.0)
|
23
|
+
mocha
|
24
|
+
proxies
|
25
|
+
s3!
|
26
|
+
test-unit (>= 2.0)
|
27
|
+
trollop
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "bundler"
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require "rake/testtask"
|
5
|
+
require "rake/rdoctask"
|
6
|
+
|
7
|
+
Rake::TestTask.new(:test) do |test|
|
8
|
+
test.libs << "lib" << "test"
|
9
|
+
test.pattern = "test/**/*_test.rb"
|
10
|
+
test.verbose = true
|
11
|
+
end
|
12
|
+
|
13
|
+
Rake::RDocTask.new do |rdoc|
|
14
|
+
rdoc.rdoc_dir = "rdoc"
|
15
|
+
rdoc.title = "s3 #{S3::VERSION}"
|
16
|
+
rdoc.rdoc_files.include("README.rdoc")
|
17
|
+
rdoc.rdoc_files.include("lib/**/*.rb")
|
18
|
+
end
|
19
|
+
|
20
|
+
task :default => :test
|
data/lib/s3/connection.rb
CHANGED
@@ -4,7 +4,7 @@ module S3
|
|
4
4
|
class Connection
|
5
5
|
include Parser
|
6
6
|
|
7
|
-
attr_accessor :access_key_id, :secret_access_key, :use_ssl, :timeout, :debug
|
7
|
+
attr_accessor :access_key_id, :secret_access_key, :use_ssl, :timeout, :debug, :proxy
|
8
8
|
alias :use_ssl? :use_ssl
|
9
9
|
|
10
10
|
# Creates new connection object.
|
@@ -18,12 +18,15 @@ module S3
|
|
18
18
|
# (false by default)
|
19
19
|
# * <tt>:timeout</tt> - Timeout to use by the Net::HTTP object
|
20
20
|
# (60 by default)
|
21
|
+
# * <tt>:proxy</tt> - Hash for Net::HTTP Proxy settings
|
22
|
+
# { :host => "proxy.mydomain.com", :port => "80, :user => "user_a", :password => "secret" }
|
21
23
|
def initialize(options = {})
|
22
24
|
@access_key_id = options.fetch(:access_key_id)
|
23
25
|
@secret_access_key = options.fetch(:secret_access_key)
|
24
26
|
@use_ssl = options.fetch(:use_ssl, false)
|
25
27
|
@debug = options.fetch(:debug, false)
|
26
28
|
@timeout = options.fetch(:timeout, 60)
|
29
|
+
@proxy = options.fetch(:proxy, nil)
|
27
30
|
end
|
28
31
|
|
29
32
|
# Makes request with given HTTP method, sets missing parameters,
|
@@ -157,8 +160,12 @@ module S3
|
|
157
160
|
use_ssl ? 443 : 80
|
158
161
|
end
|
159
162
|
|
163
|
+
def proxy_settings
|
164
|
+
@proxy.values_at(:host, :port, :user, :password) unless @proxy.blank?
|
165
|
+
end
|
166
|
+
|
160
167
|
def http(host)
|
161
|
-
http = Net::HTTP.new(host, port)
|
168
|
+
http = Net::HTTP.new(host, port, *proxy_settings)
|
162
169
|
http.set_debug_output(STDOUT) if @debug
|
163
170
|
http.use_ssl = @use_ssl
|
164
171
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if @use_ssl
|
data/lib/s3/object.rb
CHANGED
@@ -17,7 +17,7 @@ module S3
|
|
17
17
|
# of the objects are the same, and both have the same buckets (see
|
18
18
|
# Bucket equality)
|
19
19
|
def ==(other)
|
20
|
-
self.key == other.key
|
20
|
+
other.equal?(self) || (other.instance_of?(self.class) && self.key == other.key && self.bucket == other.bucket)
|
21
21
|
end
|
22
22
|
|
23
23
|
# Returns full key of the object: e.g. <tt>bucket-name/object/key.ext</tt>
|
data/lib/s3/service.rb
CHANGED
@@ -3,7 +3,7 @@ module S3
|
|
3
3
|
include Parser
|
4
4
|
include Proxies
|
5
5
|
|
6
|
-
attr_reader :access_key_id, :secret_access_key, :use_ssl
|
6
|
+
attr_reader :access_key_id, :secret_access_key, :use_ssl, :proxy
|
7
7
|
|
8
8
|
# Compares service to other, by <tt>access_key_id</tt> and
|
9
9
|
# <tt>secret_access_key</tt>
|
@@ -28,6 +28,9 @@ module S3
|
|
28
28
|
@use_ssl = options.fetch(:use_ssl, false)
|
29
29
|
@timeout = options.fetch(:timeout, 60)
|
30
30
|
@debug = options.fetch(:debug, false)
|
31
|
+
|
32
|
+
raise ArgumentError, "Missing proxy settings. Must specify at least :host." if options[:proxy] && !options[:proxy][:host]
|
33
|
+
@proxy = options.fetch(:proxy, nil)
|
31
34
|
end
|
32
35
|
|
33
36
|
# Returns all buckets in the service and caches the result (see
|
@@ -70,7 +73,8 @@ module S3
|
|
70
73
|
:secret_access_key => @secret_access_key,
|
71
74
|
:use_ssl => @use_ssl,
|
72
75
|
:timeout => @timeout,
|
73
|
-
:debug => @debug
|
76
|
+
:debug => @debug,
|
77
|
+
:proxy => @proxy)
|
74
78
|
end
|
75
79
|
@connection
|
76
80
|
end
|
data/lib/s3/version.rb
CHANGED
data/s3.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.expand_path("../lib/s3/version", __FILE__)
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "s3"
|
7
|
+
s.version = S3::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Jakub Kuźma"]
|
10
|
+
s.email = ["qoobaa@gmail.com"]
|
11
|
+
s.homepage = "http://jah.pl/projects/s3.html"
|
12
|
+
s.summary = "Library for accessing S3 objects and buckets, with command line tool"
|
13
|
+
s.description = "S3 library provides access to Amazon's Simple Storage Service. It supports both: European and US buckets through REST API."
|
14
|
+
|
15
|
+
s.required_rubygems_version = ">= 1.3.6"
|
16
|
+
s.rubyforge_project = "s3"
|
17
|
+
|
18
|
+
s.add_dependency "trollop"
|
19
|
+
s.add_dependency "proxies"
|
20
|
+
s.add_development_dependency "test-unit", ">= 2.0"
|
21
|
+
s.add_development_dependency "mocha"
|
22
|
+
s.add_development_dependency "bundler", ">= 1.0.0"
|
23
|
+
|
24
|
+
s.files = `git ls-files`.split("\n")
|
25
|
+
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
26
|
+
s.require_path = "lib"
|
27
|
+
end
|
data/test/bucket_test.rb
ADDED
@@ -0,0 +1,215 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class BucketTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@bucket_vhost = S3::Bucket.send(:new, nil, "Data-Bucket")
|
6
|
+
@bucket_path = S3::Bucket.send(:new, nil, "Data_Bucket")
|
7
|
+
@bucket = @bucket_vhost
|
8
|
+
|
9
|
+
@bucket_location = "EU"
|
10
|
+
@bucket_location_body = <<-EOLocation
|
11
|
+
<?xml version="1.0" encoding="UTF-8"?>\n<LocationConstraint xmlns="http://s3.amazonaws.com/doc/2006-03-01/">EU</LocationConstraint>
|
12
|
+
EOLocation
|
13
|
+
|
14
|
+
@response_location = Net::HTTPOK.new("1.1", "200", "OK")
|
15
|
+
@response_location.stubs(:body).returns(@bucket_location_body)
|
16
|
+
|
17
|
+
@bucket_owned_by_you_body = <<-EOOwnedByYou
|
18
|
+
<?xml version="1.0" encoding="UTF-8"?>\n<Error> <Code>BucketAlreadyOwnedByYou</Code> <Message>Your previous request to create the named bucket succeeded and you already own it.</Message> <BucketName>bucket</BucketName> <RequestId>117D08EA0EC6E860</RequestId> <HostId>4VpMSvmJ+G5+DLtVox6O5cZNgdPlYcjCu3l0n4HjDe01vPxxuk5eTAtcAkUynRyV</HostId> </Error>
|
19
|
+
EOOwnedByYou
|
20
|
+
|
21
|
+
@reponse_owned_by_you = Net::HTTPConflict.new("1.1", "409", "Conflict")
|
22
|
+
@reponse_owned_by_you.stubs(:body).returns(@bucket_owned_by_you_body)
|
23
|
+
|
24
|
+
@bucket_already_exists_body = <<-EOAlreadyExists
|
25
|
+
<?xml version="1.0" encoding="UTF-8"?>\n<Error> <Code>BucketAlreadyExists</Code> <Message>The requested bucket name is not available. The bucket namespace is shared by all users of the system. Please select a different name and try again.</Message> <BucketName>bucket</BucketName> <RequestId>4C154D32807C92BD</RequestId> <HostId>/xyHQgXcUXTZQhoO+NUBzbaxbFrIhKlyuaRHFnmcId0bMePvY9Zwg+dyk2LYE4g5</HostId> </Error>
|
26
|
+
EOAlreadyExists
|
27
|
+
|
28
|
+
@reponse_already_exists = Net::HTTPConflict.new("1.1", "409", "Conflict")
|
29
|
+
@response_already_exists.stubs(:body).returns(@bucket_already_exists_body)
|
30
|
+
|
31
|
+
@objects_list_empty = []
|
32
|
+
@objects_list = [
|
33
|
+
S3::Object.send(:new, @bucket, :key => "obj1"),
|
34
|
+
S3::Object.send(:new, @bucket, :key => "obj2")
|
35
|
+
]
|
36
|
+
|
37
|
+
@response_objects_list_empty_body = <<-EOEmpty
|
38
|
+
<?xml version="1.0" encoding="UTF-8"?>\n<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <Name>bucket</Name> <Prefix></Prefix> <Marker></Marker> <MaxKeys>1000</MaxKeys> <IsTruncated>false</IsTruncated> </ListBucketResult>
|
39
|
+
EOEmpty
|
40
|
+
|
41
|
+
@response_objects_list_empty = Net::HTTPOK.new("1.1", "200", "OK")
|
42
|
+
@response_objects_list_empty.stubs(:body).returns(@response_objects_list_empty_body)
|
43
|
+
|
44
|
+
@response_objects_list_body = <<-EOObjects
|
45
|
+
<?xml version="1.0" encoding="UTF-8"?>\n<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <Name>bucket</Name> <Prefix></Prefix> <Marker></Marker> <MaxKeys>1000</MaxKeys> <IsTruncated>false</IsTruncated> <Contents> <Key>obj1</Key> <LastModified>2009-07-03T10:17:33.000Z</LastModified> <ETag>"99519cdf14c255e580e1b7bca85a458c"</ETag> <Size>1729</Size> <Owner> <ID>df864aeb6f42be43f1d9e60aaabe3f15e245b035a4b79d1cfe36c4deaec67205</ID> <DisplayName>owner</DisplayName> </Owner> <StorageClass>STANDARD</StorageClass> </Contents> <Contents> <Key>obj2</Key> <LastModified>2009-07-03T11:17:33.000Z</LastModified> <ETag>"99519cdf14c255e586e1b12bca85a458c"</ETag> <Size>179</Size> <Owner> <ID>df864aeb6f42be43f1d9e60aaabe3f17e247b037a4b79d1cfe36c4deaec67205</ID> <DisplayName>owner</DisplayName> </Owner> <StorageClass>STANDARD</StorageClass> </Contents> </ListBucketResult>
|
46
|
+
EOObjects
|
47
|
+
|
48
|
+
@response_objects_list = Net::HTTPOK.new("1.1", "200", "OK")
|
49
|
+
@response_objects_list.stubs(:body).returns(@response_objects_list_body)
|
50
|
+
end
|
51
|
+
|
52
|
+
test "name valid" do
|
53
|
+
assert_raise ArgumentError do S3::Bucket.send(:new, nil, "") end # should not be valid with empty name
|
54
|
+
assert_raise ArgumentError do S3::Bucket.send(:new, nil, "10.0.0.1") end # should not be valid with IP as name
|
55
|
+
assert_raise ArgumentError do S3::Bucket.send(:new, nil, "as") end # should not be valid with name shorter than 3 characters
|
56
|
+
assert_raise ArgumentError do S3::Bucket.send(:new, nil, "a" * 256) end # should not be valid with name longer than 255 characters
|
57
|
+
assert_raise ArgumentError do S3::Bucket.send(:new, nil, ".asdf") end # should not allow special characters as first character
|
58
|
+
assert_raise ArgumentError do S3::Bucket.send(:new, nil, "-asdf") end # should not allow special characters as first character
|
59
|
+
assert_raise ArgumentError do S3::Bucket.send(:new, nil, "_asdf") end # should not allow special characters as first character
|
60
|
+
|
61
|
+
assert_nothing_raised do
|
62
|
+
S3::Bucket.send(:new, nil, "a-a-")
|
63
|
+
S3::Bucket.send(:new, nil, "a.a.")
|
64
|
+
S3::Bucket.send(:new, nil, "a_a_")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
test "path prefix" do
|
69
|
+
expected = ""
|
70
|
+
actual = @bucket_vhost.path_prefix
|
71
|
+
assert_equal expected, actual
|
72
|
+
|
73
|
+
expected = "Data_Bucket/"
|
74
|
+
actual = @bucket_path.path_prefix
|
75
|
+
assert_equal expected, actual
|
76
|
+
end
|
77
|
+
|
78
|
+
test "host" do
|
79
|
+
expected = "Data-Bucket.s3.amazonaws.com"
|
80
|
+
actual = @bucket_vhost.host
|
81
|
+
assert_equal expected, actual
|
82
|
+
|
83
|
+
expected = "s3.amazonaws.com"
|
84
|
+
actual = @bucket_path.host
|
85
|
+
assert_equal expected, actual
|
86
|
+
end
|
87
|
+
|
88
|
+
test "vhost" do
|
89
|
+
assert @bucket_vhost.vhost?
|
90
|
+
assert ! @bucket_path.vhost?
|
91
|
+
end
|
92
|
+
|
93
|
+
test "exists" do
|
94
|
+
@bucket.expects(:retrieve).returns(@bucket_vhost)
|
95
|
+
assert @bucket.exists?
|
96
|
+
|
97
|
+
@bucket.expects(:retrieve).raises(S3::Error::NoSuchBucket.new(nil, nil))
|
98
|
+
assert ! @bucket.exists?
|
99
|
+
end
|
100
|
+
|
101
|
+
test "location and parse location" do
|
102
|
+
@bucket.expects(:bucket_request).with(:get, { :params => { :location => nil } }).returns(@response_location)
|
103
|
+
|
104
|
+
expected = @bucket_location
|
105
|
+
actual = @bucket.location
|
106
|
+
assert_equal expected, actual
|
107
|
+
|
108
|
+
@bucket.stubs(:bucket_request).with(:get, { :params => { :location => nil } })
|
109
|
+
actual = @bucket.location
|
110
|
+
assert_equal expected, actual
|
111
|
+
end
|
112
|
+
|
113
|
+
test "save" do
|
114
|
+
@bucket.expects(:bucket_request).with(:put, { :headers => {} })
|
115
|
+
assert @bucket.save
|
116
|
+
# mock ensures that bucket_request was called
|
117
|
+
end
|
118
|
+
|
119
|
+
test "save failure owned by you" do
|
120
|
+
@bucket.expects(:bucket_request).with(:put, { :headers => {} }).raises(S3::Error::BucketAlreadyOwnedByYou.new(409, @response_owned_by_you))
|
121
|
+
assert_raise S3::Error::BucketAlreadyOwnedByYou do
|
122
|
+
@bucket.save
|
123
|
+
end
|
124
|
+
|
125
|
+
@bucket.expects(:bucket_request).with(:put, { :headers => {} }).raises(S3::Error::BucketAlreadyExists.new(409, @response_already_exists))
|
126
|
+
assert_raise S3::Error::BucketAlreadyExists do
|
127
|
+
@bucket.save
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
test "objects" do
|
132
|
+
@bucket.expects(:list_bucket).returns(@objects_list_empty)
|
133
|
+
expected = @objects_list_empty
|
134
|
+
actual = @bucket.objects
|
135
|
+
assert_equal expected, actual
|
136
|
+
|
137
|
+
@bucket.stubs(:list_bucket).returns(@objects_list_empty)
|
138
|
+
actual = @bucket.objects
|
139
|
+
assert_equal expected, actual
|
140
|
+
|
141
|
+
@bucket.stubs(:list_bucket).returns(@objects_list)
|
142
|
+
|
143
|
+
expected = @objects_list
|
144
|
+
actual = @bucket.objects
|
145
|
+
assert_equal expected, actual
|
146
|
+
end
|
147
|
+
|
148
|
+
test "list bucket and parse objects" do
|
149
|
+
@bucket.expects(:bucket_request).with(:get, :params => { :test=>true }).returns(@response_objects_list_empty)
|
150
|
+
expected = @objects_list_empty
|
151
|
+
actual = @bucket.objects.find_all(:test => true)
|
152
|
+
assert_equal expected, actual
|
153
|
+
|
154
|
+
@bucket.expects(:bucket_request).with(:get, :params => { :test => true }).returns(@response_objects_list)
|
155
|
+
expected = @objects_list
|
156
|
+
actual = @bucket.objects.find_all(:test => true)
|
157
|
+
assert_equal expected, actual
|
158
|
+
end
|
159
|
+
|
160
|
+
test "destroy" do
|
161
|
+
@bucket.expects(:bucket_request).with(:delete)
|
162
|
+
assert @bucket.destroy
|
163
|
+
end
|
164
|
+
|
165
|
+
test "objects build" do
|
166
|
+
@bucket.stubs(:bucket_request)
|
167
|
+
|
168
|
+
expected = "object_name"
|
169
|
+
actual = @bucket.objects.build("object_name")
|
170
|
+
assert_kind_of S3::Object, actual
|
171
|
+
assert_equal expected, actual.key
|
172
|
+
end
|
173
|
+
|
174
|
+
test "objects find first" do
|
175
|
+
assert_nothing_raised do
|
176
|
+
S3::Object.any_instance.stubs(:retrieve).returns(S3::Object.send(:new, nil, :key => "obj2"))
|
177
|
+
expected = "obj2"
|
178
|
+
actual = @bucket.objects.find_first("obj2")
|
179
|
+
assert_equal "obj2", actual.key
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
test "objects find first fail" do
|
184
|
+
assert_raise S3::Error::NoSuchKey do
|
185
|
+
S3::Object.any_instance.stubs(:retrieve).raises(S3::Error::NoSuchKey.new(404, nil))
|
186
|
+
@bucket.objects.find_first("obj3")
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
test "objects find all on empty list" do
|
191
|
+
@bucket.stubs(:list_bucket).returns(@objects_list_empty)
|
192
|
+
assert_nothing_raised do
|
193
|
+
expected = @objects_list_empty
|
194
|
+
actual = @bucket.objects.find_all
|
195
|
+
assert_equal expected, actual
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
test "objects find all" do
|
200
|
+
@bucket.stubs(:list_bucket).returns(@objects_list)
|
201
|
+
assert_nothing_raised do
|
202
|
+
expected = @objects_list
|
203
|
+
actual = @bucket.objects.find_all
|
204
|
+
assert_equal expected, actual
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
test "objects destroy all" do
|
209
|
+
@bucket.stubs(:list_bucket).returns(@objects_list)
|
210
|
+
@bucket.objects.each do |obj|
|
211
|
+
obj.expects(:destroy)
|
212
|
+
end
|
213
|
+
@bucket.objects.destroy_all
|
214
|
+
end
|
215
|
+
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class ConnectionTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@connection = S3::Connection.new(
|
6
|
+
:access_key_id => "12345678901234567890",
|
7
|
+
:secret_access_key => "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDF"
|
8
|
+
)
|
9
|
+
@http_request = Net::HTTP.new("")
|
10
|
+
@response_ok = Net::HTTPOK.new("1.1", "200", "OK")
|
11
|
+
@response_not_found = Net::HTTPNotFound.new("1.1", "404", "Not Found")
|
12
|
+
@response_error = Net::HTTPInternalServerError.new("1.1", "500", "Internal Server Error")
|
13
|
+
@response_temporary_redirect = Net::HTTPInternalServerError.new("1.1", "307", "Temporary Redirect")
|
14
|
+
@connection.stubs(:http).returns(@http_request)
|
15
|
+
|
16
|
+
@http_request.stubs(:start).returns(@response_ok)
|
17
|
+
end
|
18
|
+
|
19
|
+
test "handle response not modify response when ok" do
|
20
|
+
assert_nothing_raised do
|
21
|
+
response = @connection.request(
|
22
|
+
:get,
|
23
|
+
:host => "s3.amazonaws.com",
|
24
|
+
:path => "/"
|
25
|
+
)
|
26
|
+
assert_equal @response_ok, response
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
test "handle response throws exception when error" do
|
31
|
+
response_body = <<-EOFakeBody
|
32
|
+
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
|
33
|
+
<Error>
|
34
|
+
<Code>NoSuchBucket</Code>
|
35
|
+
<Message>The specified bucket does not exist</Message>
|
36
|
+
</Error>
|
37
|
+
EOFakeBody
|
38
|
+
|
39
|
+
@http_request.stubs(:start).returns(@response_not_found)
|
40
|
+
@response_not_found.stubs(:body).returns(response_body)
|
41
|
+
|
42
|
+
assert_raise S3::Error::NoSuchBucket do
|
43
|
+
response = @connection.request(
|
44
|
+
:get,
|
45
|
+
:host => "data.example.com.s3.amazonaws.com",
|
46
|
+
:path => "/"
|
47
|
+
)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
test "handle response throws standard exception when error" do
|
52
|
+
@http_request.stubs(:start).returns(@response_error)
|
53
|
+
@response_error.stubs(:body)
|
54
|
+
assert_raise S3::Error::ResponseError do
|
55
|
+
response = @connection.request(
|
56
|
+
:get,
|
57
|
+
:host => "data.example.com.s3.amazonaws.com",
|
58
|
+
:path => "/"
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
@response_error.stubs(:body).returns("")
|
63
|
+
assert_raise S3::Error::ResponseError do
|
64
|
+
response = @connection.request(
|
65
|
+
:get,
|
66
|
+
:host => "data.example.com.s3.amazonaws.com",
|
67
|
+
:path => "/"
|
68
|
+
)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
test "parse params empty" do
|
73
|
+
expected = ""
|
74
|
+
actual = S3::Connection.parse_params({})
|
75
|
+
assert_equal expected, actual
|
76
|
+
end
|
77
|
+
|
78
|
+
test "parse params only interesting params" do
|
79
|
+
expected = ""
|
80
|
+
actual = S3::Connection.parse_params(:param1 => "1", :maxkeys => "2")
|
81
|
+
assert_equal expected, actual
|
82
|
+
end
|
83
|
+
|
84
|
+
test "parse params remove underscore" do
|
85
|
+
expected = "max-keys=100"
|
86
|
+
actual = S3::Connection.parse_params(:max_keys => 100)
|
87
|
+
assert_equal expected, actual
|
88
|
+
end
|
89
|
+
|
90
|
+
test "parse params with and without values" do
|
91
|
+
params = S3::Connection.parse_params(:max_keys => 100, :prefix => nil)
|
92
|
+
|
93
|
+
splitted_params = params.split("&")
|
94
|
+
assert_equal 2, splitted_params.length
|
95
|
+
assert splitted_params.include?("max-keys=100")
|
96
|
+
assert splitted_params.include?("prefix")
|
97
|
+
end
|
98
|
+
|
99
|
+
test "headers empty" do
|
100
|
+
expected = {}
|
101
|
+
actual = S3::Connection.parse_headers({})
|
102
|
+
assert_equal expected, actual
|
103
|
+
end
|
104
|
+
|
105
|
+
test "parse only interesting headers" do
|
106
|
+
expected = {}
|
107
|
+
actual = S3::Connection.parse_headers(
|
108
|
+
:accept => "text/*, text/html, text/html;level=1, */*",
|
109
|
+
:accept_charset => "iso-8859-2, unicode-1-1;q=0.8"
|
110
|
+
)
|
111
|
+
assert_equal expected, actual
|
112
|
+
end
|
113
|
+
|
114
|
+
test "parse headers remove underscore" do
|
115
|
+
expected = {
|
116
|
+
"content-type" => nil,
|
117
|
+
"x-amz-acl" => nil,
|
118
|
+
"if-modified-since" => nil,
|
119
|
+
"if-unmodified-since" => nil,
|
120
|
+
"if-match" => nil,
|
121
|
+
"if-none-match" => nil,
|
122
|
+
"content-disposition" => nil,
|
123
|
+
"content-encoding" => nil
|
124
|
+
}
|
125
|
+
actual = S3::Connection.parse_headers(
|
126
|
+
:content_type => nil,
|
127
|
+
:x_amz_acl => nil,
|
128
|
+
:if_modified_since => nil,
|
129
|
+
:if_unmodified_since => nil,
|
130
|
+
:if_match => nil,
|
131
|
+
:if_none_match => nil,
|
132
|
+
:content_disposition => nil,
|
133
|
+
:content_encoding => nil
|
134
|
+
)
|
135
|
+
assert_equal expected, actual
|
136
|
+
end
|
137
|
+
|
138
|
+
test "parse headers with values" do
|
139
|
+
expected = {
|
140
|
+
"content-type" => "text/html",
|
141
|
+
"x-amz-acl" => "public-read",
|
142
|
+
"if-modified-since" => "today",
|
143
|
+
"if-unmodified-since" => "tomorrow",
|
144
|
+
"if-match" => "1234",
|
145
|
+
"if-none-match" => "1243",
|
146
|
+
"content-disposition" => "inline",
|
147
|
+
"content-encoding" => "gzip"
|
148
|
+
}
|
149
|
+
actual = S3::Connection.parse_headers(
|
150
|
+
:content_type => "text/html",
|
151
|
+
:x_amz_acl => "public-read",
|
152
|
+
:if_modified_since => "today",
|
153
|
+
:if_unmodified_since => "tomorrow",
|
154
|
+
:if_match => "1234",
|
155
|
+
:if_none_match => "1243",
|
156
|
+
:content_disposition => "inline",
|
157
|
+
:content_encoding => "gzip"
|
158
|
+
)
|
159
|
+
assert_equal expected, actual
|
160
|
+
end
|
161
|
+
|
162
|
+
test "parse headers with range" do
|
163
|
+
expected = {
|
164
|
+
"range" => "bytes=0-100"
|
165
|
+
}
|
166
|
+
actual = S3::Connection.parse_headers(
|
167
|
+
:range => 0..100
|
168
|
+
)
|
169
|
+
assert_equal expected, actual
|
170
|
+
end
|
171
|
+
|
172
|
+
test "response.body is nil on TemporaryRedirect" do
|
173
|
+
@http_request.stubs(:start).returns(@response_temporary_redirect)
|
174
|
+
@response_temporary_redirect.stubs(:body).returns(nil)
|
175
|
+
|
176
|
+
assert_nothing_raised do
|
177
|
+
response = @connection.request(
|
178
|
+
:get,
|
179
|
+
:host => "data.example.com.s3.amazonaws.com",
|
180
|
+
:path => "/"
|
181
|
+
)
|
182
|
+
assert_equal nil, response
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
test "response body with new host on TemporaryRedirect" do
|
187
|
+
response_body = <<-EOFakeBody
|
188
|
+
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>
|
189
|
+
<Error>
|
190
|
+
<Code>TemporaryRedirect</Code>
|
191
|
+
<Message>Please re-send this request to the specified temporary endpoint. Continue to use the original request endpoint for future requests.</Message>
|
192
|
+
<RequestId>24A0BB91158D470B</RequestId>
|
193
|
+
<Bucket>data.example.com</Bucket>
|
194
|
+
<HostId>DFcq9ktw5HvWZLduutz8fnVzqtXLwIZcAezc7mgyS7lJ2ux+RChY4qAJGa2fQDjV</HostId>
|
195
|
+
<Endpoint>data.example.com.s3-external-3.amazonaws.com</Endpoint>
|
196
|
+
</Error>"
|
197
|
+
EOFakeBody
|
198
|
+
|
199
|
+
@response_temporary_redirect.stubs(:body).returns(response_body)
|
200
|
+
|
201
|
+
assert_nothing_raised do
|
202
|
+
response = @connection.request(
|
203
|
+
:get,
|
204
|
+
:host => "data.example.com.s3.amazonaws.com",
|
205
|
+
:path => "/"
|
206
|
+
)
|
207
|
+
assert_equal @response_ok, response
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
data/test/object_test.rb
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "test_helper"
|
3
|
+
|
4
|
+
class ObjectTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@service = S3::Service.new(
|
7
|
+
:access_key_id => "1234",
|
8
|
+
:secret_access_key => "1337"
|
9
|
+
)
|
10
|
+
@bucket_images = S3::Bucket.send(:new, @service, "images")
|
11
|
+
@object_lena = S3::Object.send(:new, @bucket_images, :key => "Lena.png")
|
12
|
+
@object_lena.content = "test"
|
13
|
+
@object_carmen = S3::Object.send(:new, @bucket_images, :key => "Carmen.png")
|
14
|
+
|
15
|
+
@response_binary = Net::HTTPOK.new("1.1", "200", "OK")
|
16
|
+
@response_binary.stubs(:body).returns("test".respond_to?(:force_encoding) ? "test".force_encoding(Encoding::BINARY) : "test")
|
17
|
+
@response_binary["etag"] = ""
|
18
|
+
@response_binary["content-type"] = "image/png"
|
19
|
+
@response_binary["content-disposition"] = "inline"
|
20
|
+
@response_binary["content-encoding"] = nil
|
21
|
+
@response_binary["last-modified"] = Time.now.httpdate
|
22
|
+
@response_binary["content-length"] = 20
|
23
|
+
|
24
|
+
@xml_body = <<-EOXML
|
25
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
26
|
+
<CopyObjectResult> <LastModified>#{Time.now.httpdate}</LastModified> <ETag>"etag"</ETag> </CopyObjectResult>
|
27
|
+
EOXML
|
28
|
+
@response_xml = Net::HTTPOK.new("1.1", "200", "OK")
|
29
|
+
@response_xml.stubs(:body).returns(@xml_body)
|
30
|
+
end
|
31
|
+
|
32
|
+
test "initializing" do
|
33
|
+
assert_raise ArgumentError do S3::Object.send(:new, nil, :key => "") end # should not allow empty key
|
34
|
+
assert_raise ArgumentError do S3::Object.send(:new, nil, :key => "//") end # should not allow key with double slash
|
35
|
+
|
36
|
+
assert_nothing_raised do
|
37
|
+
S3::Object.send(:new, nil, :key => "Lena.png")
|
38
|
+
S3::Object.send(:new, nil, :key => "Lena playboy.png")
|
39
|
+
S3::Object.send(:new, nil, :key => "Lena Söderberg.png")
|
40
|
+
S3::Object.send(:new, nil, :key => "/images/pictures/test images/Lena not full.png")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
test "==" do
|
45
|
+
expected = false
|
46
|
+
actual = @object_lena == nil
|
47
|
+
assert_equal(expected, actual)
|
48
|
+
end
|
49
|
+
|
50
|
+
test "full key" do
|
51
|
+
expected = "images/Lena.png"
|
52
|
+
actual = @object_lena.full_key
|
53
|
+
assert_equal expected, actual
|
54
|
+
end
|
55
|
+
|
56
|
+
test "url" do
|
57
|
+
bucket1 = S3::Bucket.send(:new, @service, "images")
|
58
|
+
|
59
|
+
object11 = S3::Object.send(:new, bucket1, :key => "Lena.png")
|
60
|
+
expected = "http://images.s3.amazonaws.com/Lena.png"
|
61
|
+
actual = object11.url
|
62
|
+
assert_equal expected, actual
|
63
|
+
|
64
|
+
object12 = S3::Object.send(:new, bucket1, :key => "Lena Söderberg.png")
|
65
|
+
expected = "http://images.s3.amazonaws.com/Lena%20S%C3%B6derberg.png"
|
66
|
+
actual = object12.url
|
67
|
+
assert_equal expected, actual
|
68
|
+
|
69
|
+
bucket2 = S3::Bucket.send(:new, @service, "images_new")
|
70
|
+
|
71
|
+
object21 = S3::Object.send(:new, bucket2, :key => "Lena.png")
|
72
|
+
expected = "http://s3.amazonaws.com/images_new/Lena.png"
|
73
|
+
actual = object21.url
|
74
|
+
assert_equal expected, actual
|
75
|
+
end
|
76
|
+
|
77
|
+
test "cname url" do
|
78
|
+
bucket1 = S3::Bucket.send(:new, @service, "images.example.com")
|
79
|
+
|
80
|
+
object11 = S3::Object.send(:new, bucket1, :key => "Lena.png")
|
81
|
+
expected = "http://images.example.com/Lena.png"
|
82
|
+
actual = object11.cname_url
|
83
|
+
assert_equal expected, actual
|
84
|
+
|
85
|
+
object12 = S3::Object.send(:new, bucket1, :key => "Lena Söderberg.png")
|
86
|
+
expected = "http://images.example.com/Lena%20S%C3%B6derberg.png"
|
87
|
+
actual = object12.cname_url
|
88
|
+
assert_equal expected, actual
|
89
|
+
|
90
|
+
bucket2 = S3::Bucket.send(:new, @service, "images_new")
|
91
|
+
|
92
|
+
object21 = S3::Object.send(:new, bucket2, :key => "Lena.png")
|
93
|
+
expected = nil
|
94
|
+
actual = object21.cname_url
|
95
|
+
assert_equal expected, actual
|
96
|
+
end
|
97
|
+
|
98
|
+
test "destroy" do
|
99
|
+
@object_lena.expects(:object_request).with(:delete)
|
100
|
+
assert @object_lena.destroy
|
101
|
+
end
|
102
|
+
|
103
|
+
test "save" do
|
104
|
+
@object_lena.expects(:object_request).with(:put, :body=>"test", :headers=>{ :x_amz_acl=>"public-read", :content_type=>"application/octet-stream" }).returns(@response_binary)
|
105
|
+
assert @object_lena.save
|
106
|
+
end
|
107
|
+
|
108
|
+
test "content and parse headers" do
|
109
|
+
@object_lena.expects(:object_request).with(:get, {}).returns(@response_binary)
|
110
|
+
|
111
|
+
expected = /test/n
|
112
|
+
actual = @object_lena.content(true)
|
113
|
+
assert_match expected, actual
|
114
|
+
assert_equal "image/png", @object_lena.content_type
|
115
|
+
|
116
|
+
assert @object_lena.content
|
117
|
+
|
118
|
+
@object_lena.expects(:object_request).with(:get, {}).returns(@response_binary)
|
119
|
+
assert @object_lena.content(true)
|
120
|
+
end
|
121
|
+
|
122
|
+
test "retrieve" do
|
123
|
+
@object_lena.expects(:object_request).with(:head, {}).returns(@response_binary)
|
124
|
+
assert @object_lena.retrieve
|
125
|
+
end
|
126
|
+
|
127
|
+
test "exists" do
|
128
|
+
@object_lena.expects(:retrieve).returns(true)
|
129
|
+
assert @object_lena.exists?
|
130
|
+
|
131
|
+
@object_carmen.expects(:retrieve).raises(S3::Error::NoSuchKey.new(nil, nil))
|
132
|
+
assert ! @object_carmen.exists?
|
133
|
+
end
|
134
|
+
|
135
|
+
test "ACL writer" do
|
136
|
+
expected = nil
|
137
|
+
actual = @object_lena.acl
|
138
|
+
assert_equal expected, actual
|
139
|
+
|
140
|
+
assert @object_lena.acl = :public_read
|
141
|
+
|
142
|
+
expected = "public-read"
|
143
|
+
actual = @object_lena.acl
|
144
|
+
assert_equal expected, actual
|
145
|
+
|
146
|
+
assert @object_lena.acl = :private
|
147
|
+
|
148
|
+
expected = "private"
|
149
|
+
actual = @object_lena.acl
|
150
|
+
assert_equal expected, actual
|
151
|
+
end
|
152
|
+
|
153
|
+
test "copy" do
|
154
|
+
@bucket_images.expects(:bucket_request).with(:put, :path => "Lena-copy.png", :headers => { :x_amz_acl => "public-read", :content_type => "application/octet-stream", :x_amz_copy_source => "images/Lena.png", :x_amz_metadata_directive => "REPLACE" }).returns(@response_xml)
|
155
|
+
|
156
|
+
new_object = @object_lena.copy(:key => "Lena-copy.png")
|
157
|
+
|
158
|
+
assert_equal "Lena-copy.png", new_object.key
|
159
|
+
assert_equal "Lena.png", @object_lena.key
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class ServiceTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@buckets_list_body = <<-EOBuckets
|
6
|
+
<?xml version="1.0" encoding="UTF-8"?>\n<ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <Owner> <ID>123u1odhkhfoadf</ID> <DisplayName>JohnDoe</DisplayName> </Owner> <Buckets> <Bucket> <Name>data.example.com</Name> <CreationDate>2009-07-02T11:56:58.000Z</CreationDate> </Bucket> <Bucket> <Name>images</Name> <CreationDate>2009-06-05T12:26:33.000Z</CreationDate> </Bucket> </Buckets> </ListAllMyBucketsResult>
|
7
|
+
EOBuckets
|
8
|
+
|
9
|
+
@bucket_not_exists = <<-EOBucketNoexists
|
10
|
+
<?xml version="1.0" encoding="UTF-8"?>\n<Error> <Code>NoSuchBucket</Code> <Message>The specified bucket does not exists</Message> <BucketName>data2.example.com</BucketName> <RequestId>8D7519AAE74E9E99</RequestId> <HostId>DvKnnNSMnPHd1oXukyRaFNv8Lg/bpwhuUtY8Kj7eDLbaIrIT8JebSnHwi89AK1P+</HostId> </Error>
|
11
|
+
EOBucketNoexists
|
12
|
+
|
13
|
+
@bucket_exists = <<-EOBucketexists
|
14
|
+
<?xml version="1.0" encoding="UTF-8"?>\n<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <Name>data.synergypeople.net</Name> <Prefix></Prefix> <Marker></Marker> <MaxKeys>1000</MaxKeys> <IsTruncated>false</IsTruncated> </ListBucketResult>
|
15
|
+
EOBucketexists
|
16
|
+
|
17
|
+
@service_empty_buckets_list = S3::Service.new(
|
18
|
+
:access_key_id => "12345678901234567890",
|
19
|
+
:secret_access_key => "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDF"
|
20
|
+
)
|
21
|
+
@response_empty_buckets_list = Net::HTTPOK.new("1.1", "200", "OK")
|
22
|
+
@service_empty_buckets_list.stubs(:service_request).returns(@response_empty_buckets_list)
|
23
|
+
@response_empty_buckets_list.stubs(:body).returns(@buckets_empty_list_body)
|
24
|
+
|
25
|
+
@service_buckets_list = S3::Service.new(
|
26
|
+
:access_key_id => "12345678901234567890",
|
27
|
+
:secret_access_key => "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDF"
|
28
|
+
)
|
29
|
+
@response_buckets_list = Net::HTTPOK.new("1.1", "200", "OK")
|
30
|
+
@service_buckets_list.stubs(:service_request).returns(@response_buckets_list)
|
31
|
+
@response_buckets_list.stubs(:body).returns(@buckets_list_body)
|
32
|
+
|
33
|
+
@service_bucket_exists = S3::Service.new(
|
34
|
+
:access_key_id => "12345678901234567890",
|
35
|
+
:secret_access_key => "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDF"
|
36
|
+
)
|
37
|
+
@response_bucket_exists = Net::HTTPNotFound.new("1.1", "200", "OK")
|
38
|
+
@service_bucket_exists.stubs(:service_request).returns(@response_bucket_exists)
|
39
|
+
@response_bucket_exists.stubs(:body).returns(@bucket_exists)
|
40
|
+
|
41
|
+
@service_bucket_not_exists = S3::Service.new(
|
42
|
+
:access_key_id => "12345678901234567890",
|
43
|
+
:secret_access_key => "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDF"
|
44
|
+
)
|
45
|
+
@response_bucket_not_exists = Net::HTTPNotFound.new("1.1", "404", "Not Found")
|
46
|
+
@service_bucket_not_exists.stubs(:service_request).raises(S3::Error::NoSuchBucket.new(404, @response_bucket_not_exists))
|
47
|
+
@response_bucket_not_exists.stubs(:body).returns(@bucket_not_exists)
|
48
|
+
|
49
|
+
@buckets_empty_list = []
|
50
|
+
@buckets_empty_list_body = <<-EOEmptyBuckets
|
51
|
+
<?xml version="1.0" encoding="UTF-8"?>\n<ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <Owner> <ID>123u1odhkhfoadf</ID> <DisplayName>JohnDoe</DisplayName> </Owner> <Buckets> </Buckets> </ListAllMyBucketsResult>
|
52
|
+
EOEmptyBuckets
|
53
|
+
|
54
|
+
@buckets_list = [
|
55
|
+
S3::Bucket.send(:new, @service_buckets_list, "data.example.com"),
|
56
|
+
S3::Bucket.send(:new, @service_buckets_list, "images")
|
57
|
+
]
|
58
|
+
end
|
59
|
+
|
60
|
+
test "buckets and parse buckets empty" do
|
61
|
+
expected = @buckets_empty_list
|
62
|
+
actual = @service_empty_buckets_list.buckets
|
63
|
+
assert_equal expected.length, actual.length
|
64
|
+
assert_equal expected, actual
|
65
|
+
end
|
66
|
+
|
67
|
+
test "buckets and parse buckets" do
|
68
|
+
expected = @buckets_list
|
69
|
+
# ugly hack
|
70
|
+
actual = @service_buckets_list.buckets.map { |obj| obj }
|
71
|
+
assert_equal expected, actual
|
72
|
+
end
|
73
|
+
|
74
|
+
test "buckets build" do
|
75
|
+
@service_empty_buckets_list.stubs(:service_request)
|
76
|
+
|
77
|
+
expected = "bucket_name"
|
78
|
+
actual = @service_empty_buckets_list.buckets.build("bucket_name")
|
79
|
+
assert_kind_of S3::Bucket, actual
|
80
|
+
assert_equal expected, actual.name
|
81
|
+
end
|
82
|
+
|
83
|
+
test "buckets find first" do
|
84
|
+
assert_nothing_raised do
|
85
|
+
actual = @service_buckets_list.buckets.find_first("data.example.com")
|
86
|
+
assert_equal "data.example.com", actual.name
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
test "buckets find first fail" do
|
91
|
+
assert_raise S3::Error::NoSuchBucket do
|
92
|
+
@service_bucket_not_exists.buckets.find_first("data2.example.com")
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
test "buckets find all on empty list" do
|
97
|
+
assert_nothing_raised do
|
98
|
+
expected = @buckets_empty_list
|
99
|
+
actual = @service_empty_buckets_list.buckets.find_all
|
100
|
+
assert_equal expected, actual
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
test "buckets find all" do
|
105
|
+
assert_nothing_raised do
|
106
|
+
expected = @buckets_list
|
107
|
+
actual = @service_buckets_list.buckets.find_all
|
108
|
+
assert_equal expected, actual
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class SignatureTest < Test::Unit::TestCase
|
4
|
+
# from http://docs.amazonwebservices.com/AmazonS3/latest/RESTAuthentication.html
|
5
|
+
test "signature for object get" do
|
6
|
+
request = Net::HTTP::Get.new("/photos/puppy.jpg")
|
7
|
+
request["host"] = "johnsmith.s3.amazonaws.com"
|
8
|
+
request["date"] = "Tue, 27 Mar 2007 19:36:42 +0000"
|
9
|
+
|
10
|
+
actual = S3::Signature.generate(
|
11
|
+
:host => request["host"],
|
12
|
+
:request => request,
|
13
|
+
:access_key_id => "0PN5J17HBGZHT7JJ3X82",
|
14
|
+
:secret_access_key => "uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o"
|
15
|
+
)
|
16
|
+
expected = "AWS 0PN5J17HBGZHT7JJ3X82:xXjDGYUmKxnwqr5KXNPGldn5LbA="
|
17
|
+
assert_equal expected, actual
|
18
|
+
end
|
19
|
+
|
20
|
+
test "signature for object put" do
|
21
|
+
request = Net::HTTP::Put.new("/photos/puppy.jpg");
|
22
|
+
request["content-type"] = "image/jpeg"
|
23
|
+
request["content-length"] = "94328"
|
24
|
+
request["host"] = "johnsmith.s3.amazonaws.com"
|
25
|
+
request["date"] = "Tue, 27 Mar 2007 21:15:45 +0000"
|
26
|
+
|
27
|
+
actual = S3::Signature.generate(
|
28
|
+
:host => request["host"],
|
29
|
+
:request => request,
|
30
|
+
:access_key_id => "0PN5J17HBGZHT7JJ3X82",
|
31
|
+
:secret_access_key => "uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o"
|
32
|
+
)
|
33
|
+
expected = "AWS 0PN5J17HBGZHT7JJ3X82:hcicpDDvL9SsO6AkvxqmIWkmOuQ="
|
34
|
+
assert_equal expected, actual
|
35
|
+
end
|
36
|
+
|
37
|
+
test "signature for list" do
|
38
|
+
request = Net::HTTP::Get.new("/?prefix=photos&max-keys=50&marker=puppy");
|
39
|
+
request["user-agent"] = "Mozilla/5.0"
|
40
|
+
request["host"] = "johnsmith.s3.amazonaws.com"
|
41
|
+
request["date"] = "Tue, 27 Mar 2007 19:42:41 +0000"
|
42
|
+
|
43
|
+
actual = S3::Signature.generate(
|
44
|
+
:host => request["host"],
|
45
|
+
:request => request,
|
46
|
+
:access_key_id => "0PN5J17HBGZHT7JJ3X82",
|
47
|
+
:secret_access_key => "uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o"
|
48
|
+
)
|
49
|
+
expected = "AWS 0PN5J17HBGZHT7JJ3X82:jsRt/rhG+Vtp88HrYL706QhE4w4="
|
50
|
+
assert_equal expected, actual
|
51
|
+
end
|
52
|
+
|
53
|
+
test "signature for fetch" do
|
54
|
+
request = Net::HTTP::Get.new("/?acl");
|
55
|
+
request["host"] = "johnsmith.s3.amazonaws.com"
|
56
|
+
request["date"] = "Tue, 27 Mar 2007 19:44:46 +0000"
|
57
|
+
|
58
|
+
actual = S3::Signature.generate(
|
59
|
+
:host => request["host"],
|
60
|
+
:request => request,
|
61
|
+
:access_key_id => "0PN5J17HBGZHT7JJ3X82",
|
62
|
+
:secret_access_key => "uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o"
|
63
|
+
)
|
64
|
+
expected = "AWS 0PN5J17HBGZHT7JJ3X82:thdUi9VAkzhkniLj96JIrOPGi0g="
|
65
|
+
assert_equal expected, actual
|
66
|
+
end
|
67
|
+
|
68
|
+
test "signature for delete" do
|
69
|
+
request = Net::HTTP::Delete.new("/johnsmith/photos/puppy.jpg");
|
70
|
+
request["user-agent"] = "dotnet"
|
71
|
+
request["host"] = "s3.amazonaws.com"
|
72
|
+
request["date"] = "Tue, 27 Mar 2007 21:20:27 +0000"
|
73
|
+
request["x-amz-date"] = "Tue, 27 Mar 2007 21:20:26 +0000"
|
74
|
+
|
75
|
+
actual = S3::Signature.generate(
|
76
|
+
:host => request["host"],
|
77
|
+
:request => request,
|
78
|
+
:access_key_id => "0PN5J17HBGZHT7JJ3X82",
|
79
|
+
:secret_access_key => "uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o"
|
80
|
+
)
|
81
|
+
expected = "AWS 0PN5J17HBGZHT7JJ3X82:k3nL7gH3+PadhTEVn5Ip83xlYzk="
|
82
|
+
assert_equal expected, actual
|
83
|
+
end
|
84
|
+
|
85
|
+
test "signature for upload" do
|
86
|
+
request = Net::HTTP::Put.new("/db-backup.dat.gz");
|
87
|
+
request["user-agent"] = "curl/7.15.5"
|
88
|
+
request["host"] = "static.johnsmith.net:8080"
|
89
|
+
request["date"] = "Tue, 27 Mar 2007 21:06:08 +0000"
|
90
|
+
request["x-amz-acl"] = "public-read"
|
91
|
+
request["content-type"] = "application/x-download"
|
92
|
+
request["content-md5"] = "4gJE4saaMU4BqNR0kLY+lw=="
|
93
|
+
# FIXME: Net::HTTP doesn't allow to have multiple headers with the same name
|
94
|
+
# request.add_field add additional spaces (breaks signature)
|
95
|
+
#request["x-amz-meta-reviewedby"] = "joe@johnsmith.net"
|
96
|
+
#request["x-amz-meta-reviewedby"] = "jane@johnsmith.net"
|
97
|
+
request["x-amz-meta-reviewedby"] = "joe@johnsmith.net,jane@johnsmith.net"
|
98
|
+
request["x-amz-meta-filechecksum"] = "0x02661779"
|
99
|
+
request["x-amz-meta-checksumalgorithm"] = "crc32"
|
100
|
+
request["content-disposition"] = "attachment; filename=database.dat"
|
101
|
+
request["content-encoding"] = "gzip"
|
102
|
+
request["content-length"] = "5913339"
|
103
|
+
|
104
|
+
actual = S3::Signature.generate(
|
105
|
+
:host => "static.johnsmith.net",
|
106
|
+
:request => request,
|
107
|
+
:access_key_id => "0PN5J17HBGZHT7JJ3X82",
|
108
|
+
:secret_access_key => "uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o"
|
109
|
+
)
|
110
|
+
expected = "AWS 0PN5J17HBGZHT7JJ3X82:C0FlOtU8Ylb9KDTpZqYkZPX91iI="
|
111
|
+
assert_equal expected, actual
|
112
|
+
end
|
113
|
+
|
114
|
+
test "signature for list all my buckets" do
|
115
|
+
request = Net::HTTP::Get.new("/");
|
116
|
+
request["host"] = "s3.amazonaws.com"
|
117
|
+
request["date"] = "Wed, 28 Mar 2007 01:29:59 +0000"
|
118
|
+
|
119
|
+
actual = S3::Signature.generate(
|
120
|
+
:host => request["host"],
|
121
|
+
:request => request,
|
122
|
+
:access_key_id => "0PN5J17HBGZHT7JJ3X82",
|
123
|
+
:secret_access_key => "uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o"
|
124
|
+
)
|
125
|
+
expected = "AWS 0PN5J17HBGZHT7JJ3X82:Db+gepJSUbZKwpx1FR0DLtEYoZA="
|
126
|
+
assert_equal expected, actual
|
127
|
+
end
|
128
|
+
|
129
|
+
test "signature for unicode keys" do
|
130
|
+
request = Net::HTTP::Get.new("/dictionary/fran%C3%A7ais/pr%c3%a9f%c3%a8re");
|
131
|
+
request["host"] = "s3.amazonaws.com"
|
132
|
+
request["date"] = "Wed, 28 Mar 2007 01:49:49 +0000"
|
133
|
+
|
134
|
+
actual = S3::Signature.generate(
|
135
|
+
:host => request["host"],
|
136
|
+
:request => request,
|
137
|
+
:access_key_id => "0PN5J17HBGZHT7JJ3X82",
|
138
|
+
:secret_access_key => "uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o"
|
139
|
+
)
|
140
|
+
expected = "AWS 0PN5J17HBGZHT7JJ3X82:dxhSBHoI6eVSPcXJqEghlUzZMnY="
|
141
|
+
assert_equal expected, actual
|
142
|
+
end
|
143
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: s3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 19
|
5
4
|
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 0
|
8
7
|
- 3
|
9
|
-
-
|
10
|
-
version: 0.3.
|
8
|
+
- 1
|
9
|
+
version: 0.3.1
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- "Jakub Ku\xC5\xBAma"
|
@@ -15,7 +14,7 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date: 2010-
|
17
|
+
date: 2010-09-04 00:00:00 +02:00
|
19
18
|
default_executable:
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
@@ -26,7 +25,6 @@ dependencies:
|
|
26
25
|
requirements:
|
27
26
|
- - ">="
|
28
27
|
- !ruby/object:Gem::Version
|
29
|
-
hash: 3
|
30
28
|
segments:
|
31
29
|
- 0
|
32
30
|
version: "0"
|
@@ -40,7 +38,6 @@ dependencies:
|
|
40
38
|
requirements:
|
41
39
|
- - ">="
|
42
40
|
- !ruby/object:Gem::Version
|
43
|
-
hash: 3
|
44
41
|
segments:
|
45
42
|
- 0
|
46
43
|
version: "0"
|
@@ -54,7 +51,6 @@ dependencies:
|
|
54
51
|
requirements:
|
55
52
|
- - ">="
|
56
53
|
- !ruby/object:Gem::Version
|
57
|
-
hash: 3
|
58
54
|
segments:
|
59
55
|
- 2
|
60
56
|
- 0
|
@@ -69,14 +65,29 @@ dependencies:
|
|
69
65
|
requirements:
|
70
66
|
- - ">="
|
71
67
|
- !ruby/object:Gem::Version
|
72
|
-
hash: 3
|
73
68
|
segments:
|
74
69
|
- 0
|
75
70
|
version: "0"
|
76
71
|
type: :development
|
77
72
|
version_requirements: *id004
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: bundler
|
75
|
+
prerelease: false
|
76
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
segments:
|
82
|
+
- 1
|
83
|
+
- 0
|
84
|
+
- 0
|
85
|
+
version: 1.0.0
|
86
|
+
type: :development
|
87
|
+
version_requirements: *id005
|
78
88
|
description: "S3 library provides access to Amazon's Simple Storage Service. It supports both: European and US buckets through REST API."
|
79
|
-
email:
|
89
|
+
email:
|
90
|
+
- qoobaa@gmail.com
|
80
91
|
executables:
|
81
92
|
- s3
|
82
93
|
extensions: []
|
@@ -84,22 +95,33 @@ extensions: []
|
|
84
95
|
extra_rdoc_files: []
|
85
96
|
|
86
97
|
files:
|
98
|
+
- .gitignore
|
99
|
+
- Gemfile
|
100
|
+
- Gemfile.lock
|
101
|
+
- LICENSE
|
102
|
+
- README.rdoc
|
103
|
+
- Rakefile
|
87
104
|
- bin/s3
|
88
105
|
- extra/s3_attachment_fu.rb
|
89
106
|
- extra/s3_paperclip.rb
|
90
107
|
- lib/s3.rb
|
91
|
-
- lib/s3/object.rb
|
92
|
-
- lib/s3/parser.rb
|
93
|
-
- lib/s3/signature.rb
|
94
108
|
- lib/s3/bucket.rb
|
95
|
-
- lib/s3/exceptions.rb
|
96
|
-
- lib/s3/service.rb
|
97
|
-
- lib/s3/version.rb
|
98
109
|
- lib/s3/buckets_extension.rb
|
99
110
|
- lib/s3/connection.rb
|
111
|
+
- lib/s3/exceptions.rb
|
112
|
+
- lib/s3/object.rb
|
100
113
|
- lib/s3/objects_extension.rb
|
101
|
-
-
|
102
|
-
-
|
114
|
+
- lib/s3/parser.rb
|
115
|
+
- lib/s3/service.rb
|
116
|
+
- lib/s3/signature.rb
|
117
|
+
- lib/s3/version.rb
|
118
|
+
- s3.gemspec
|
119
|
+
- test/bucket_test.rb
|
120
|
+
- test/connection_test.rb
|
121
|
+
- test/object_test.rb
|
122
|
+
- test/service_test.rb
|
123
|
+
- test/signature_test.rb
|
124
|
+
- test/test_helper.rb
|
103
125
|
has_rdoc: true
|
104
126
|
homepage: http://jah.pl/projects/s3.html
|
105
127
|
licenses: []
|
@@ -114,7 +136,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
114
136
|
requirements:
|
115
137
|
- - ">="
|
116
138
|
- !ruby/object:Gem::Version
|
117
|
-
hash: 3
|
118
139
|
segments:
|
119
140
|
- 0
|
120
141
|
version: "0"
|
@@ -123,7 +144,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
123
144
|
requirements:
|
124
145
|
- - ">="
|
125
146
|
- !ruby/object:Gem::Version
|
126
|
-
hash: 23
|
127
147
|
segments:
|
128
148
|
- 1
|
129
149
|
- 3
|
@@ -131,7 +151,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
131
151
|
version: 1.3.6
|
132
152
|
requirements: []
|
133
153
|
|
134
|
-
rubyforge_project:
|
154
|
+
rubyforge_project: s3
|
135
155
|
rubygems_version: 1.3.7
|
136
156
|
signing_key:
|
137
157
|
specification_version: 3
|