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/.gitignore +1 -0
- data/README.rdoc +15 -15
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/bin/{stree → s3} +3 -3
- data/extra/{stree_backend.rb → s3_backend.rb} +9 -9
- data/lib/s3.rb +24 -0
- data/lib/{stree → s3}/bucket.rb +2 -2
- data/lib/{stree → s3}/connection.rb +1 -1
- data/lib/{stree → s3}/exceptions.rb +2 -2
- data/lib/{stree → s3}/object.rb +2 -2
- data/lib/{stree → s3}/parser.rb +1 -1
- data/lib/{stree → s3}/roxy/moxie.rb +1 -1
- data/lib/{stree → s3}/roxy/proxy.rb +1 -1
- data/lib/{stree → s3}/service.rb +1 -1
- data/lib/{stree → s3}/signature.rb +1 -1
- data/test/bucket_test.rb +34 -34
- data/test/connection_test.rb +16 -15
- data/test/object_test.rb +27 -35
- data/test/service_test.rb +9 -9
- data/test/signature_test.rb +8 -8
- data/test/test_helper.rb +1 -1
- metadata +16 -16
- data/lib/stree.rb +0 -24
data/.gitignore
CHANGED
data/README.rdoc
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
=
|
1
|
+
= S3
|
2
2
|
|
3
|
-
* repository: http://github.com/qoobaa/
|
4
|
-
* issue tracker: http://github.com/qoobaa/
|
5
|
-
* rdoc: http://qoobaa.github.com/
|
3
|
+
* repository: http://github.com/qoobaa/s3
|
4
|
+
* issue tracker: http://github.com/qoobaa/s3/issues
|
5
|
+
* rdoc: http://qoobaa.github.com/s3
|
6
6
|
|
7
7
|
== Usage
|
8
8
|
|
@@ -11,37 +11,37 @@ Coming soon, see Rdoc documentation.
|
|
11
11
|
== Command tool usage
|
12
12
|
|
13
13
|
You have to pass access key id (-a) and secret access key (-s) to the
|
14
|
-
command line tool.
|
14
|
+
command line tool. S3 reads ACCESS_KEY_ID and SECRET_ACCESS_KEY
|
15
15
|
environment variables and uses them by default, so if you don't want
|
16
16
|
to pass them each time, export them (e.g. in .bashrc file).
|
17
17
|
|
18
18
|
* list buckets
|
19
|
-
|
19
|
+
s3 bucket
|
20
20
|
|
21
21
|
* create bucket
|
22
|
-
|
22
|
+
s3 bucket add name-of-bucket
|
23
23
|
|
24
24
|
* list objects in bucket
|
25
|
-
|
25
|
+
s3 bucket show name-of-bucket
|
26
26
|
|
27
27
|
* destroy bucket
|
28
|
-
|
28
|
+
s3 bucket remove name-of-bucket
|
29
29
|
|
30
30
|
* list objects (in all buckets)
|
31
|
-
|
31
|
+
s3 object
|
32
32
|
|
33
33
|
* show the object information
|
34
|
-
|
34
|
+
s3 object show bucket_name/path/to/object.extension
|
35
35
|
|
36
36
|
* download the content of the object
|
37
|
-
|
37
|
+
s3 object show bucket_name/path/to/object.extension filename_to_store_the_content.extension
|
38
38
|
|
39
39
|
* show the content of the object to STDOUT
|
40
|
-
|
40
|
+
s3 object show bucket_name/path/to/object.extension -
|
41
41
|
|
42
42
|
You can also pass --help to the commmands like:
|
43
|
-
|
44
|
-
|
43
|
+
s3 bucket add --help
|
44
|
+
s3 object show --help
|
45
45
|
|
46
46
|
== Copyright
|
47
47
|
|
data/Rakefile
CHANGED
@@ -9,7 +9,7 @@ begin
|
|
9
9
|
gem.name = "s3"
|
10
10
|
gem.summary = %Q{Library for accessing S3 objects and buckets, with command line tool}
|
11
11
|
gem.email = "qoobaa@gmail.com"
|
12
|
-
gem.homepage = "http://github.com/qoobaa/
|
12
|
+
gem.homepage = "http://github.com/qoobaa/s3"
|
13
13
|
gem.authors = ["Jakub Kuźma", "Mirosław Boruta"]
|
14
14
|
gem.add_dependency "trollop", ">=1.14"
|
15
15
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
@@ -51,7 +51,7 @@ Rake::RDocTask.new do |rdoc|
|
|
51
51
|
end
|
52
52
|
|
53
53
|
rdoc.rdoc_dir = 'rdoc'
|
54
|
-
rdoc.title = "
|
54
|
+
rdoc.title = "s3 #{version}"
|
55
55
|
rdoc.rdoc_files.include('README*')
|
56
56
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
57
57
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.1
|
data/bin/{stree → s3}
RENAMED
@@ -3,11 +3,11 @@
|
|
3
3
|
$: << File.expand_path(File.dirname(__FILE__) + "/../lib")
|
4
4
|
|
5
5
|
require "trollop"
|
6
|
-
require "
|
6
|
+
require "s3"
|
7
7
|
|
8
8
|
# HELPER METHODS
|
9
9
|
|
10
|
-
include
|
10
|
+
include S3
|
11
11
|
|
12
12
|
def list_buckets(service)
|
13
13
|
service.buckets.each do |bucket|
|
@@ -82,7 +82,7 @@ BUCKET_SUBCOMMANDS = %w(add remove show)
|
|
82
82
|
OBJECT_SUBCOMMANDS = %w(add remove show)
|
83
83
|
|
84
84
|
global_options = Trollop::options do
|
85
|
-
banner "
|
85
|
+
banner "s3 command line tool"
|
86
86
|
opt :access_key_id, "Your access key id to AWS", :type => :string, :default => ACCESS_KEY_ID
|
87
87
|
opt :secret_access_key, "Your secret access key to AWS", :type => :string, :default => SECRET_ACCESS_KEY
|
88
88
|
opt :debug, "Debug mode", :type => :flag, :default => false
|
@@ -1,14 +1,14 @@
|
|
1
1
|
require "singleton"
|
2
|
-
require "
|
2
|
+
require "s3"
|
3
3
|
|
4
|
-
#
|
4
|
+
# S3 Backend for attachment-fu plugin. After installing attachment-fu
|
5
5
|
# plugin, copy the file to:
|
6
6
|
# +vendor/plugins/attachment-fu/lib/technoweenie/attachment_fu/backends+
|
7
7
|
#
|
8
|
-
# To configure
|
9
|
-
# application, e.g. +config/initializers/
|
8
|
+
# To configure S3Backend create initializer file in your Rails
|
9
|
+
# application, e.g. +config/initializers/s3_backend.rb+.
|
10
10
|
#
|
11
|
-
# Technoweenie::AttachmentFu::Backends::
|
11
|
+
# Technoweenie::AttachmentFu::Backends::S3Backend.configuration do |config|
|
12
12
|
# config.access_key_id = "..." # your access key id
|
13
13
|
# config.secret_access_key = "..." # your secret access key
|
14
14
|
# config.bucket_name = "..." # default bucket name to store attachments
|
@@ -18,9 +18,9 @@ require "stree"
|
|
18
18
|
module Technoweenie
|
19
19
|
module AttachmentFu
|
20
20
|
module Backends
|
21
|
-
module
|
21
|
+
module S3Backend
|
22
22
|
|
23
|
-
#
|
23
|
+
# S3Backend configuration class
|
24
24
|
class Configuration
|
25
25
|
include Singleton
|
26
26
|
|
@@ -29,7 +29,7 @@ module Technoweenie
|
|
29
29
|
attr_accessor *ATTRIBUTES
|
30
30
|
end
|
31
31
|
|
32
|
-
# Method used to configure
|
32
|
+
# Method used to configure S3Backend, see the example above
|
33
33
|
def self.configuration
|
34
34
|
if block_given?
|
35
35
|
yield Configuration.instance
|
@@ -39,7 +39,7 @@ module Technoweenie
|
|
39
39
|
|
40
40
|
# :nodoc:
|
41
41
|
def self.included(base)
|
42
|
-
include
|
42
|
+
include S3
|
43
43
|
|
44
44
|
service = Service.new(:access_key_id => configuration.access_key_id,
|
45
45
|
:secret_access_key => configuration.secret_access_key,
|
data/lib/s3.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require "base64"
|
2
|
+
require "digest/md5"
|
3
|
+
require "forwardable"
|
4
|
+
require "net/http"
|
5
|
+
require "net/https"
|
6
|
+
require "openssl"
|
7
|
+
require "rexml/document"
|
8
|
+
require "time"
|
9
|
+
|
10
|
+
require "s3/roxy/moxie"
|
11
|
+
require "s3/roxy/proxy"
|
12
|
+
|
13
|
+
require "s3/parser"
|
14
|
+
require "s3/bucket"
|
15
|
+
require "s3/connection"
|
16
|
+
require "s3/exceptions"
|
17
|
+
require "s3/object"
|
18
|
+
require "s3/service"
|
19
|
+
require "s3/signature"
|
20
|
+
|
21
|
+
module S3
|
22
|
+
# Default (and only) host serving S3 stuff
|
23
|
+
HOST = "s3.amazonaws.com"
|
24
|
+
end
|
data/lib/{stree → s3}/bucket.rb
RENAMED
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module S3
|
2
2
|
class Bucket
|
3
3
|
include Parser
|
4
4
|
extend Roxy::Moxie
|
@@ -10,7 +10,7 @@ module Stree
|
|
10
10
|
private_class_method :new
|
11
11
|
|
12
12
|
# Retrieves the bucket information from the server. Raises an
|
13
|
-
#
|
13
|
+
# S3::Error exception if the bucket doesn't exist or you don't
|
14
14
|
# have access to it, etc.
|
15
15
|
def retrieve
|
16
16
|
list_bucket(:max_keys => 0)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module S3
|
2
2
|
module Error
|
3
3
|
|
4
4
|
# All responses with a code between 300 and 599 that contain an
|
@@ -30,7 +30,7 @@ module Stree
|
|
30
30
|
# Descendant of ResponseError suitable for that exception code or ResponseError class
|
31
31
|
# if no class found
|
32
32
|
def self.exception(code)
|
33
|
-
|
33
|
+
S3::Error.const_get(code)
|
34
34
|
rescue NameError
|
35
35
|
ResponseError
|
36
36
|
end
|
data/lib/{stree → s3}/object.rb
RENAMED
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module S3
|
2
2
|
|
3
3
|
# Class responsible for handling objects stored in S3 buckets
|
4
4
|
class Object
|
@@ -77,7 +77,7 @@ module Stree
|
|
77
77
|
# Copies the file to another key and/or bucket.
|
78
78
|
# ==== Options:
|
79
79
|
# +key+:: new key to store object in
|
80
|
-
# +bucket+:: new bucket to store object in (instance of
|
80
|
+
# +bucket+:: new bucket to store object in (instance of S3::Bucket)
|
81
81
|
# +acl+:: acl of the copied object (default: "public-read")
|
82
82
|
# +content_type+:: content type of the copied object (default: "application/octet-stream")
|
83
83
|
def copy(options = {})
|
data/lib/{stree → s3}/parser.rb
RENAMED
@@ -20,7 +20,7 @@
|
|
20
20
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
21
|
# SOFTWARE.
|
22
22
|
|
23
|
-
module
|
23
|
+
module S3
|
24
24
|
module Roxy # :nodoc:all
|
25
25
|
# The very simple proxy class that provides a basic pass-through
|
26
26
|
# mechanism between the proxy owner and the proxy target.
|
data/lib/{stree → s3}/service.rb
RENAMED
data/test/bucket_test.rb
CHANGED
@@ -2,8 +2,8 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class BucketTest < Test::Unit::TestCase
|
4
4
|
def setup
|
5
|
-
@bucket_vhost =
|
6
|
-
@bucket_path =
|
5
|
+
@bucket_vhost = S3::Bucket.send(:new, nil, "data-bucket")
|
6
|
+
@bucket_path = S3::Bucket.send(:new, nil, "data_bucket")
|
7
7
|
@bucket = @bucket_vhost
|
8
8
|
|
9
9
|
@response_location = Net::HTTPOK.new("1.1", "200", "OK")
|
@@ -27,8 +27,8 @@ class BucketTest < Test::Unit::TestCase
|
|
27
27
|
|
28
28
|
@objects_list_empty = []
|
29
29
|
@objects_list = [
|
30
|
-
|
31
|
-
|
30
|
+
S3::Object.send(:new, @bucket, :key => "obj1"),
|
31
|
+
S3::Object.send(:new, @bucket, :key => "obj2")
|
32
32
|
]
|
33
33
|
|
34
34
|
@response_objects_list_empty = Net::HTTPOK.new("1.1", "200", "OK")
|
@@ -45,18 +45,18 @@ class BucketTest < Test::Unit::TestCase
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def test_name_valid
|
48
|
-
assert_raise ArgumentError do
|
49
|
-
assert_raise ArgumentError do
|
50
|
-
assert_raise ArgumentError do
|
51
|
-
assert_raise ArgumentError do
|
52
|
-
assert_raise ArgumentError do
|
53
|
-
assert_raise ArgumentError do
|
54
|
-
assert_raise ArgumentError do
|
48
|
+
assert_raise ArgumentError do S3::Bucket.send(:new, nil, "") end # should not be valid with empty name
|
49
|
+
assert_raise ArgumentError do S3::Bucket.send(:new, nil, "10.0.0.1") end # should not be valid with IP as name
|
50
|
+
assert_raise ArgumentError do S3::Bucket.send(:new, nil, "as") end # should not be valid with name shorter than 3 characters
|
51
|
+
assert_raise ArgumentError do S3::Bucket.send(:new, nil, "a"*256) end # should not be valid with name longer than 255 characters
|
52
|
+
assert_raise ArgumentError do S3::Bucket.send(:new, nil, ".asdf") end # should not allow special characters as first character
|
53
|
+
assert_raise ArgumentError do S3::Bucket.send(:new, nil, "-asdf") end # should not allow special characters as first character
|
54
|
+
assert_raise ArgumentError do S3::Bucket.send(:new, nil, "_asdf") end # should not allow special characters as first character
|
55
55
|
|
56
56
|
assert_nothing_raised do
|
57
|
-
|
58
|
-
|
59
|
-
|
57
|
+
S3::Bucket.send(:new, nil, "a-a-")
|
58
|
+
S3::Bucket.send(:new, nil, "a.a.")
|
59
|
+
S3::Bucket.send(:new, nil, "a_a_")
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
@@ -89,7 +89,7 @@ class BucketTest < Test::Unit::TestCase
|
|
89
89
|
mock(@bucket).retrieve { @bucket_vhost }
|
90
90
|
assert @bucket.exists?
|
91
91
|
|
92
|
-
mock(@bucket).retrieve { raise
|
92
|
+
mock(@bucket).retrieve { raise S3::Error::NoSuchBucket.new(nil, nil) }
|
93
93
|
assert ! @bucket.exists?
|
94
94
|
end
|
95
95
|
|
@@ -112,41 +112,41 @@ class BucketTest < Test::Unit::TestCase
|
|
112
112
|
end
|
113
113
|
|
114
114
|
def test_save_failure_owned_by_you
|
115
|
-
mock(@bucket).bucket_request(:put, {:headers=>{}}) { raise
|
116
|
-
assert_raise
|
115
|
+
mock(@bucket).bucket_request(:put, {:headers=>{}}) { raise S3::Error::BucketAlreadyOwnedByYou.new(409, @response_owned_by_you) }
|
116
|
+
assert_raise S3::Error::BucketAlreadyOwnedByYou do
|
117
117
|
@bucket.save
|
118
118
|
end
|
119
119
|
|
120
|
-
mock(@bucket).bucket_request(:put, {:headers=>{}}) { raise
|
121
|
-
assert_raise
|
120
|
+
mock(@bucket).bucket_request(:put, {:headers=>{}}) { raise S3::Error::BucketAlreadyExists.new(409, @response_already_exists) }
|
121
|
+
assert_raise S3::Error::BucketAlreadyExists do
|
122
122
|
@bucket.save
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
126
|
def test_objects
|
127
|
-
mock(@bucket).
|
127
|
+
mock(@bucket).list_bucket { @objects_list_empty }
|
128
128
|
expected = @objects_list_empty
|
129
129
|
actual = @bucket.objects
|
130
130
|
assert_equal expected, actual
|
131
131
|
|
132
|
-
stub(@bucket).
|
132
|
+
stub(@bucket).list_bucket { flunk "should load objects from cache" }
|
133
133
|
actual = @bucket.objects
|
134
134
|
assert_equal expected, actual
|
135
135
|
|
136
|
-
stub(@bucket).
|
136
|
+
stub(@bucket).list_bucket { @objects_list }
|
137
137
|
|
138
138
|
expected = @objects_list
|
139
139
|
actual = @bucket.objects(true)
|
140
140
|
assert_equal expected, actual
|
141
141
|
end
|
142
142
|
|
143
|
-
def
|
144
|
-
mock(@bucket).bucket_request(:get, :test=>true) { @response_objects_list_empty }
|
143
|
+
def test_list_bucket_and_parse_objects
|
144
|
+
mock(@bucket).bucket_request(:get, :params => { :test=>true }) { @response_objects_list_empty }
|
145
145
|
expected = @objects_list_empty
|
146
146
|
actual = @bucket.objects.find_all(:test => true)
|
147
147
|
assert_equal expected, actual
|
148
148
|
|
149
|
-
mock(@bucket).bucket_request(:get, :test=>true) { @response_objects_list }
|
149
|
+
mock(@bucket).bucket_request(:get, :params => { :test=>true }) { @response_objects_list }
|
150
150
|
expected = @objects_list
|
151
151
|
actual = @bucket.objects.find_all(:test => true)
|
152
152
|
assert_equal expected, actual
|
@@ -162,13 +162,13 @@ class BucketTest < Test::Unit::TestCase
|
|
162
162
|
|
163
163
|
expected = "object_name"
|
164
164
|
actual = @bucket.objects.build("object_name")
|
165
|
-
assert_kind_of
|
165
|
+
assert_kind_of S3::Object, actual
|
166
166
|
assert_equal expected, actual.key
|
167
167
|
end
|
168
168
|
|
169
169
|
def test_objects_find_first
|
170
170
|
assert_nothing_raised do
|
171
|
-
stub.instance_of(
|
171
|
+
stub.instance_of(S3::Object).retrieve { S3::Object.send(:new, nil, :key => "obj2") }
|
172
172
|
expected = "obj2"
|
173
173
|
actual = @bucket.objects.find_first("obj2")
|
174
174
|
assert_equal "obj2", actual.key
|
@@ -176,14 +176,14 @@ class BucketTest < Test::Unit::TestCase
|
|
176
176
|
end
|
177
177
|
|
178
178
|
def test_objects_find_first_fail
|
179
|
-
assert_raise
|
180
|
-
stub.instance_of(
|
179
|
+
assert_raise S3::Error::NoSuchKey do
|
180
|
+
stub.instance_of(S3::Object).retrieve { raise S3::Error::NoSuchKey.new(404, nil) }
|
181
181
|
@bucket.objects.find_first("obj3")
|
182
182
|
end
|
183
183
|
end
|
184
184
|
|
185
185
|
def test_objects_find_all_on_empty_list
|
186
|
-
stub(@bucket).
|
186
|
+
stub(@bucket).list_bucket { @objects_list_empty }
|
187
187
|
assert_nothing_raised do
|
188
188
|
expected = @objects_list_empty
|
189
189
|
actual = @bucket.objects.find_all
|
@@ -192,7 +192,7 @@ class BucketTest < Test::Unit::TestCase
|
|
192
192
|
end
|
193
193
|
|
194
194
|
def test_objects_find_all
|
195
|
-
stub(@bucket).
|
195
|
+
stub(@bucket).list_bucket { @objects_list }
|
196
196
|
assert_nothing_raised do
|
197
197
|
expected = @objects_list
|
198
198
|
actual = @bucket.objects.find_all
|
@@ -201,12 +201,12 @@ class BucketTest < Test::Unit::TestCase
|
|
201
201
|
end
|
202
202
|
|
203
203
|
def test_objects_reload
|
204
|
-
stub(@bucket).
|
204
|
+
stub(@bucket).list_bucket { @objects_list_empty }
|
205
205
|
expected = @objects_list_empty
|
206
206
|
actual = @bucket.objects
|
207
207
|
assert_equal expected, actual
|
208
208
|
|
209
|
-
stub(@bucket).
|
209
|
+
stub(@bucket).list_bucket { @objects_list }
|
210
210
|
expected = @objects_list_empty
|
211
211
|
actual = @bucket.objects
|
212
212
|
assert_equal expected, actual
|
@@ -220,7 +220,7 @@ class BucketTest < Test::Unit::TestCase
|
|
220
220
|
|
221
221
|
def test_objects_destroy_all
|
222
222
|
@counter = 0
|
223
|
-
stub(@bucket).
|
223
|
+
stub(@bucket).list_bucket { @objects_list }
|
224
224
|
@bucket.objects.each do |obj|
|
225
225
|
mock(obj).destroy { @counter += 1 }
|
226
226
|
end
|
data/test/connection_test.rb
CHANGED
@@ -2,7 +2,7 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class ConnectionTest < Test::Unit::TestCase
|
4
4
|
def setup
|
5
|
-
@connection =
|
5
|
+
@connection = S3::Connection.new(
|
6
6
|
:access_key_id => "12345678901234567890",
|
7
7
|
:secret_access_key => "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDF"
|
8
8
|
)
|
@@ -27,15 +27,16 @@ class ConnectionTest < Test::Unit::TestCase
|
|
27
27
|
def test_handle_response_throws_exception_when_not_ok
|
28
28
|
response_body = <<-EOFakeBody
|
29
29
|
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
|
30
|
-
<
|
30
|
+
<Error>
|
31
31
|
<Code>NoSuchBucket</Code>
|
32
32
|
<Message>The specified bucket does not exist</Message>
|
33
|
-
</
|
33
|
+
</Error>
|
34
34
|
EOFakeBody
|
35
|
+
|
35
36
|
stub(@http_request).start { @response_not_found }
|
36
37
|
stub(@response_not_found).body { response_body }
|
37
38
|
|
38
|
-
assert_raise
|
39
|
+
assert_raise S3::Error::NoSuchBucket do
|
39
40
|
response = @connection.request(
|
40
41
|
:get,
|
41
42
|
:host => "data.example.com.s3.amazonaws.com",
|
@@ -47,7 +48,7 @@ class ConnectionTest < Test::Unit::TestCase
|
|
47
48
|
def test_handle_response_throws_standard_exception_when_not_ok
|
48
49
|
stub(@http_request).start { @response_not_found }
|
49
50
|
stub(@response_not_found).body { nil }
|
50
|
-
assert_raise
|
51
|
+
assert_raise S3::Error::ResponseError do
|
51
52
|
response = @connection.request(
|
52
53
|
:get,
|
53
54
|
:host => "data.example.com.s3.amazonaws.com",
|
@@ -56,7 +57,7 @@ class ConnectionTest < Test::Unit::TestCase
|
|
56
57
|
end
|
57
58
|
|
58
59
|
stub(@response_not_found).body { "" }
|
59
|
-
assert_raise
|
60
|
+
assert_raise S3::Error::ResponseError do
|
60
61
|
response = @connection.request(
|
61
62
|
:get,
|
62
63
|
:host => "data.example.com.s3.amazonaws.com",
|
@@ -67,37 +68,37 @@ class ConnectionTest < Test::Unit::TestCase
|
|
67
68
|
|
68
69
|
def test_parse_params_empty
|
69
70
|
expected = ""
|
70
|
-
actual =
|
71
|
+
actual = S3::Connection.parse_params({})
|
71
72
|
assert_equal expected, actual
|
72
73
|
end
|
73
74
|
|
74
75
|
def test_parse_params_only_interesting_params
|
75
76
|
expected = ""
|
76
|
-
actual =
|
77
|
+
actual = S3::Connection.parse_params(:param1 => "1", :maxkeys => "2")
|
77
78
|
assert_equal expected, actual
|
78
79
|
end
|
79
80
|
|
80
81
|
def test_parse_params_remove_underscore
|
81
82
|
expected = "max-keys=100"
|
82
|
-
actual =
|
83
|
+
actual = S3::Connection.parse_params(:max_keys => 100)
|
83
84
|
assert_equal expected, actual
|
84
85
|
end
|
85
86
|
|
86
87
|
def test_parse_params_with_and_without_values
|
87
88
|
expected = "max-keys=100&prefix"
|
88
|
-
actual =
|
89
|
+
actual = S3::Connection.parse_params(:max_keys => 100, :prefix => nil)
|
89
90
|
assert_equal expected, actual
|
90
91
|
end
|
91
92
|
|
92
93
|
def test_headers_headers_empty
|
93
94
|
expected = {}
|
94
|
-
actual =
|
95
|
+
actual = S3::Connection.parse_headers({})
|
95
96
|
assert_equal expected, actual
|
96
97
|
end
|
97
98
|
|
98
99
|
def test_parse_headers_only_interesting_headers
|
99
100
|
expected = {}
|
100
|
-
actual =
|
101
|
+
actual = S3::Connection.parse_headers(
|
101
102
|
:accept => "text/*, text/html, text/html;level=1, */*",
|
102
103
|
:accept_charset => "iso-8859-2, unicode-1-1;q=0.8"
|
103
104
|
)
|
@@ -115,7 +116,7 @@ class ConnectionTest < Test::Unit::TestCase
|
|
115
116
|
"content-disposition" => nil,
|
116
117
|
"content-encoding" => nil
|
117
118
|
}
|
118
|
-
actual =
|
119
|
+
actual = S3::Connection.parse_headers(
|
119
120
|
:content_type => nil,
|
120
121
|
:x_amz_acl => nil,
|
121
122
|
:if_modified_since => nil,
|
@@ -139,7 +140,7 @@ class ConnectionTest < Test::Unit::TestCase
|
|
139
140
|
"content-disposition" => "inline",
|
140
141
|
"content-encoding" => "gzip"
|
141
142
|
}
|
142
|
-
actual =
|
143
|
+
actual = S3::Connection.parse_headers(
|
143
144
|
:content_type => "text/html",
|
144
145
|
:x_amz_acl => "public-read",
|
145
146
|
:if_modified_since => "today",
|
@@ -156,7 +157,7 @@ class ConnectionTest < Test::Unit::TestCase
|
|
156
157
|
expected = {
|
157
158
|
"range" => "bytes=0-100"
|
158
159
|
}
|
159
|
-
actual =
|
160
|
+
actual = S3::Connection.parse_headers(
|
160
161
|
:range => 0..100
|
161
162
|
)
|
162
163
|
assert_equal expected, actual
|
data/test/object_test.rb
CHANGED
@@ -3,14 +3,14 @@ require 'test_helper'
|
|
3
3
|
|
4
4
|
class ObjectTest < Test::Unit::TestCase
|
5
5
|
def setup
|
6
|
-
@service =
|
6
|
+
@service = S3::Service.new(
|
7
7
|
:access_key_id => "1234",
|
8
8
|
:secret_access_key => "1337"
|
9
9
|
)
|
10
|
-
@bucket_images =
|
11
|
-
@object_lena =
|
10
|
+
@bucket_images = S3::Bucket.send(:new, @service, "images")
|
11
|
+
@object_lena = S3::Object.send(:new, @bucket_images, :key => "Lena.png")
|
12
12
|
@object_lena.content = "test"
|
13
|
-
@object_carmen =
|
13
|
+
@object_carmen = S3::Object.send(:new, @bucket_images, :key => "Carmen.png")
|
14
14
|
|
15
15
|
@response_binary = Net::HTTPOK.new("1.1", "200", "OK")
|
16
16
|
stub(@response_binary).body { "test".force_encoding(Encoding::BINARY) }
|
@@ -30,14 +30,14 @@ class ObjectTest < Test::Unit::TestCase
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def test_initilalize
|
33
|
-
assert_raise ArgumentError do
|
34
|
-
assert_raise ArgumentError 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
35
|
|
36
36
|
assert_nothing_raised do
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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
41
|
end
|
42
42
|
end
|
43
43
|
|
@@ -48,42 +48,42 @@ class ObjectTest < Test::Unit::TestCase
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def test_url
|
51
|
-
bucket1 =
|
51
|
+
bucket1 = S3::Bucket.send(:new, @service, "images")
|
52
52
|
|
53
|
-
object11 =
|
53
|
+
object11 = S3::Object.send(:new, bucket1, :key => "Lena.png")
|
54
54
|
expected = "http://images.s3.amazonaws.com/Lena.png"
|
55
55
|
actual = object11.url
|
56
56
|
assert_equal expected, actual
|
57
57
|
|
58
|
-
object12 =
|
58
|
+
object12 = S3::Object.send(:new, bucket1, :key => "Lena Söderberg.png")
|
59
59
|
expected = "http://images.s3.amazonaws.com/Lena%20S%C3%B6derberg.png"
|
60
60
|
actual = object12.url
|
61
61
|
assert_equal expected, actual
|
62
62
|
|
63
|
-
bucket2 =
|
63
|
+
bucket2 = S3::Bucket.send(:new, @service, "images_new")
|
64
64
|
|
65
|
-
object21 =
|
65
|
+
object21 = S3::Object.send(:new, bucket2, :key => "Lena.png")
|
66
66
|
expected = "http://s3.amazonaws.com/images_new/Lena.png"
|
67
67
|
actual = object21.url
|
68
68
|
assert_equal expected, actual
|
69
69
|
end
|
70
70
|
|
71
71
|
def test_cname_url
|
72
|
-
bucket1 =
|
72
|
+
bucket1 = S3::Bucket.send(:new, @service, "images.example.com")
|
73
73
|
|
74
|
-
object11 =
|
74
|
+
object11 = S3::Object.send(:new, bucket1, :key => "Lena.png")
|
75
75
|
expected = "http://images.example.com/Lena.png"
|
76
76
|
actual = object11.cname_url
|
77
77
|
assert_equal expected, actual
|
78
78
|
|
79
|
-
object12 =
|
79
|
+
object12 = S3::Object.send(:new, bucket1, :key => "Lena Söderberg.png")
|
80
80
|
expected = "http://images.example.com/Lena%20S%C3%B6derberg.png"
|
81
81
|
actual = object12.cname_url
|
82
82
|
assert_equal expected, actual
|
83
83
|
|
84
|
-
bucket2 =
|
84
|
+
bucket2 = S3::Bucket.send(:new, @service, "images_new")
|
85
85
|
|
86
|
-
object21 =
|
86
|
+
object21 = S3::Object.send(:new, bucket2, :key => "Lena.png")
|
87
87
|
expected = nil
|
88
88
|
actual = object21.cname_url
|
89
89
|
assert_equal expected, actual
|
@@ -95,16 +95,13 @@ class ObjectTest < Test::Unit::TestCase
|
|
95
95
|
end
|
96
96
|
|
97
97
|
def test_save
|
98
|
-
mock(@object_lena).object_request(
|
99
|
-
:put, :body=>"test",
|
100
|
-
:headers=>{ :x_amz_acl=>"public-read", :content_type=>"application/octet-stream" }
|
101
|
-
) { @response_binary }
|
98
|
+
mock(@object_lena).object_request(:put, :body=>"test", :headers=>{ :x_amz_acl=>"public-read", :content_type=>"application/octet-stream" }) { @response_binary }
|
102
99
|
|
103
100
|
assert @object_lena.save
|
104
101
|
end
|
105
102
|
|
106
103
|
def test_content_and_parse_headers
|
107
|
-
mock(@object_lena).object_request(:get) { @response_binary }
|
104
|
+
mock(@object_lena).object_request(:get, {}).times(2) { @response_binary }
|
108
105
|
|
109
106
|
expected = /test/n
|
110
107
|
actual = @object_lena.content(true) # wtf? don't work with false, maybe is not fully cleaned
|
@@ -114,8 +111,6 @@ class ObjectTest < Test::Unit::TestCase
|
|
114
111
|
stub(@object_lena).object_request(:get) { flunk "should not use connection" }
|
115
112
|
|
116
113
|
assert @object_lena.content
|
117
|
-
|
118
|
-
mock(@object_lena).object_request(:get) { @response_binary }
|
119
114
|
assert @object_lena.content(true)
|
120
115
|
end
|
121
116
|
|
@@ -128,7 +123,7 @@ class ObjectTest < Test::Unit::TestCase
|
|
128
123
|
mock(@object_lena).retrieve { true }
|
129
124
|
assert @object_lena.exists?
|
130
125
|
|
131
|
-
mock(@object_carmen).retrieve { raise
|
126
|
+
mock(@object_carmen).retrieve { raise S3::Error::NoSuchKey.new(nil, nil) }
|
132
127
|
assert ! @object_carmen.exists?
|
133
128
|
end
|
134
129
|
|
@@ -151,14 +146,11 @@ class ObjectTest < Test::Unit::TestCase
|
|
151
146
|
end
|
152
147
|
|
153
148
|
def test_copy
|
154
|
-
mock(@bucket_images).bucket_request(
|
155
|
-
:put, :path=>"Lena.png",
|
156
|
-
:headers=>{:x_amz_acl=>"public-read", :content_type=>"application/octet-stream", :x_amz_copy_source=>"images/Lena.png", :x_amz_metadata_directive=>"REPLACE"}
|
157
|
-
) { @response_xml }
|
149
|
+
mock(@bucket_images).bucket_request(: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" }) { @response_xml }
|
158
150
|
|
159
|
-
new_object = @object_lena.copy
|
151
|
+
new_object = @object_lena.copy(:key => "Lena-copy.png")
|
160
152
|
|
161
|
-
assert_equal
|
162
|
-
|
153
|
+
assert_equal "Lena-copy.png", new_object.key
|
154
|
+
assert_equal "Lena.png", @object_lena.key
|
163
155
|
end
|
164
156
|
end
|
data/test/service_test.rb
CHANGED
@@ -2,7 +2,7 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class ServiceTest < Test::Unit::TestCase
|
4
4
|
def setup
|
5
|
-
@service_empty_buckets_list =
|
5
|
+
@service_empty_buckets_list = S3::Service.new(
|
6
6
|
:access_key_id => "12345678901234567890",
|
7
7
|
:secret_access_key => "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDF"
|
8
8
|
)
|
@@ -10,7 +10,7 @@ class ServiceTest < Test::Unit::TestCase
|
|
10
10
|
stub(@service_empty_buckets_list).service_request { @response_empty_buckets_list }
|
11
11
|
stub(@response_empty_buckets_list).body { @buckets_empty_list_body }
|
12
12
|
|
13
|
-
@service_buckets_list =
|
13
|
+
@service_buckets_list = S3::Service.new(
|
14
14
|
:access_key_id => "12345678901234567890",
|
15
15
|
:secret_access_key => "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDF"
|
16
16
|
)
|
@@ -18,7 +18,7 @@ class ServiceTest < Test::Unit::TestCase
|
|
18
18
|
stub(@service_buckets_list).service_request { @response_buckets_list }
|
19
19
|
stub(@response_buckets_list).body { @buckets_list_body }
|
20
20
|
|
21
|
-
@service_bucket_exists =
|
21
|
+
@service_bucket_exists = S3::Service.new(
|
22
22
|
:access_key_id => "12345678901234567890",
|
23
23
|
:secret_access_key => "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDF"
|
24
24
|
)
|
@@ -26,12 +26,12 @@ class ServiceTest < Test::Unit::TestCase
|
|
26
26
|
stub(@service_bucket_exists).service_request { @response_bucket_exists }
|
27
27
|
stub(@response_bucket_exists).body { @bucket_exists }
|
28
28
|
|
29
|
-
@service_bucket_not_exists =
|
29
|
+
@service_bucket_not_exists = S3::Service.new(
|
30
30
|
:access_key_id => "12345678901234567890",
|
31
31
|
:secret_access_key => "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDF"
|
32
32
|
)
|
33
33
|
@response_bucket_not_exists = Net::HTTPNotFound.new("1.1", "404", "Not Found")
|
34
|
-
stub(@service_bucket_not_exists).service_request { raise
|
34
|
+
stub(@service_bucket_not_exists).service_request { raise S3::Error::NoSuchBucket.new(404, @response_bucket_not_exists) }
|
35
35
|
stub(@response_bucket_not_exists).body { @bucket_not_exists }
|
36
36
|
|
37
37
|
@buckets_empty_list = []
|
@@ -40,8 +40,8 @@ class ServiceTest < Test::Unit::TestCase
|
|
40
40
|
EOEmptyBuckets
|
41
41
|
|
42
42
|
@buckets_list = [
|
43
|
-
|
44
|
-
|
43
|
+
S3::Bucket.send(:new, @service_buckets_list, "data.example.com"),
|
44
|
+
S3::Bucket.send(:new, @service_buckets_list, "images")
|
45
45
|
]
|
46
46
|
@buckets_list_body = <<-EOBuckets
|
47
47
|
<?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>
|
@@ -93,7 +93,7 @@ class ServiceTest < Test::Unit::TestCase
|
|
93
93
|
|
94
94
|
expected = "bucket_name"
|
95
95
|
actual = @service_empty_buckets_list.buckets.build("bucket_name")
|
96
|
-
assert_kind_of
|
96
|
+
assert_kind_of S3::Bucket, actual
|
97
97
|
assert_equal expected, actual.name
|
98
98
|
end
|
99
99
|
|
@@ -105,7 +105,7 @@ class ServiceTest < Test::Unit::TestCase
|
|
105
105
|
end
|
106
106
|
|
107
107
|
def test_buckets_find_first_fail
|
108
|
-
assert_raise
|
108
|
+
assert_raise S3::Error::NoSuchBucket do
|
109
109
|
@service_bucket_not_exists.buckets.find_first("data2.example.com")
|
110
110
|
end
|
111
111
|
end
|
data/test/signature_test.rb
CHANGED
@@ -7,7 +7,7 @@ class SignatureTest < Test::Unit::TestCase
|
|
7
7
|
request["host"] = "johnsmith.s3.amazonaws.com"
|
8
8
|
request["date"] = "Tue, 27 Mar 2007 19:36:42 +0000"
|
9
9
|
|
10
|
-
actual =
|
10
|
+
actual = S3::Signature.generate(
|
11
11
|
:host => request["host"],
|
12
12
|
:request => request,
|
13
13
|
:access_key_id => "0PN5J17HBGZHT7JJ3X82",
|
@@ -24,7 +24,7 @@ class SignatureTest < Test::Unit::TestCase
|
|
24
24
|
request["host"] = "johnsmith.s3.amazonaws.com"
|
25
25
|
request["date"] = "Tue, 27 Mar 2007 21:15:45 +0000"
|
26
26
|
|
27
|
-
actual =
|
27
|
+
actual = S3::Signature.generate(
|
28
28
|
:host => request["host"],
|
29
29
|
:request => request,
|
30
30
|
:access_key_id => "0PN5J17HBGZHT7JJ3X82",
|
@@ -40,7 +40,7 @@ class SignatureTest < Test::Unit::TestCase
|
|
40
40
|
request["host"] = "johnsmith.s3.amazonaws.com"
|
41
41
|
request["date"] = "Tue, 27 Mar 2007 19:42:41 +0000"
|
42
42
|
|
43
|
-
actual =
|
43
|
+
actual = S3::Signature.generate(
|
44
44
|
:host => request["host"],
|
45
45
|
:request => request,
|
46
46
|
:access_key_id => "0PN5J17HBGZHT7JJ3X82",
|
@@ -55,7 +55,7 @@ class SignatureTest < Test::Unit::TestCase
|
|
55
55
|
request["host"] = "johnsmith.s3.amazonaws.com"
|
56
56
|
request["date"] = "Tue, 27 Mar 2007 19:44:46 +0000"
|
57
57
|
|
58
|
-
actual =
|
58
|
+
actual = S3::Signature.generate(
|
59
59
|
:host => request["host"],
|
60
60
|
:request => request,
|
61
61
|
:access_key_id => "0PN5J17HBGZHT7JJ3X82",
|
@@ -72,7 +72,7 @@ class SignatureTest < Test::Unit::TestCase
|
|
72
72
|
request["date"] = "Tue, 27 Mar 2007 21:20:27 +0000"
|
73
73
|
request["x-amz-date"] = "Tue, 27 Mar 2007 21:20:26 +0000"
|
74
74
|
|
75
|
-
actual =
|
75
|
+
actual = S3::Signature.generate(
|
76
76
|
:host => request["host"],
|
77
77
|
:request => request,
|
78
78
|
:access_key_id => "0PN5J17HBGZHT7JJ3X82",
|
@@ -101,7 +101,7 @@ class SignatureTest < Test::Unit::TestCase
|
|
101
101
|
request["content-encoding"] = "gzip"
|
102
102
|
request["content-length"] = "5913339"
|
103
103
|
|
104
|
-
actual =
|
104
|
+
actual = S3::Signature.generate(
|
105
105
|
:host => "static.johnsmith.net",
|
106
106
|
:request => request,
|
107
107
|
:access_key_id => "0PN5J17HBGZHT7JJ3X82",
|
@@ -116,7 +116,7 @@ class SignatureTest < Test::Unit::TestCase
|
|
116
116
|
request["host"] = "s3.amazonaws.com"
|
117
117
|
request["date"] = "Wed, 28 Mar 2007 01:29:59 +0000"
|
118
118
|
|
119
|
-
actual =
|
119
|
+
actual = S3::Signature.generate(
|
120
120
|
:host => request["host"],
|
121
121
|
:request => request,
|
122
122
|
:access_key_id => "0PN5J17HBGZHT7JJ3X82",
|
@@ -131,7 +131,7 @@ class SignatureTest < Test::Unit::TestCase
|
|
131
131
|
request["host"] = "s3.amazonaws.com"
|
132
132
|
request["date"] = "Wed, 28 Mar 2007 01:49:49 +0000"
|
133
133
|
|
134
|
-
actual =
|
134
|
+
actual = S3::Signature.generate(
|
135
135
|
:host => request["host"],
|
136
136
|
:request => request,
|
137
137
|
:access_key_id => "0PN5J17HBGZHT7JJ3X82",
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: s3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- "Jakub Ku\xC5\xBAma"
|
@@ -11,7 +11,7 @@ bindir: bin
|
|
11
11
|
cert_chain: []
|
12
12
|
|
13
13
|
date: 2009-10-09 00:00:00 +02:00
|
14
|
-
default_executable:
|
14
|
+
default_executable: s3
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: trollop
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
description:
|
27
27
|
email: qoobaa@gmail.com
|
28
28
|
executables:
|
29
|
-
-
|
29
|
+
- s3
|
30
30
|
extensions: []
|
31
31
|
|
32
32
|
extra_rdoc_files:
|
@@ -39,18 +39,18 @@ files:
|
|
39
39
|
- README.rdoc
|
40
40
|
- Rakefile
|
41
41
|
- VERSION
|
42
|
-
- bin/
|
43
|
-
- extra/
|
44
|
-
- lib/
|
45
|
-
- lib/
|
46
|
-
- lib/
|
47
|
-
- lib/
|
48
|
-
- lib/
|
49
|
-
- lib/
|
50
|
-
- lib/
|
51
|
-
- lib/
|
52
|
-
- lib/
|
53
|
-
- lib/
|
42
|
+
- bin/s3
|
43
|
+
- extra/s3_backend.rb
|
44
|
+
- lib/s3.rb
|
45
|
+
- lib/s3/bucket.rb
|
46
|
+
- lib/s3/connection.rb
|
47
|
+
- lib/s3/exceptions.rb
|
48
|
+
- lib/s3/object.rb
|
49
|
+
- lib/s3/parser.rb
|
50
|
+
- lib/s3/roxy/moxie.rb
|
51
|
+
- lib/s3/roxy/proxy.rb
|
52
|
+
- lib/s3/service.rb
|
53
|
+
- lib/s3/signature.rb
|
54
54
|
- test/bucket_test.rb
|
55
55
|
- test/connection_test.rb
|
56
56
|
- test/object_test.rb
|
@@ -58,7 +58,7 @@ files:
|
|
58
58
|
- test/signature_test.rb
|
59
59
|
- test/test_helper.rb
|
60
60
|
has_rdoc: true
|
61
|
-
homepage: http://github.com/qoobaa/
|
61
|
+
homepage: http://github.com/qoobaa/s3
|
62
62
|
licenses: []
|
63
63
|
|
64
64
|
post_install_message:
|
data/lib/stree.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
require "base64"
|
2
|
-
require "digest/md5"
|
3
|
-
require "forwardable"
|
4
|
-
require "net/http"
|
5
|
-
require "net/https"
|
6
|
-
require "openssl"
|
7
|
-
require "rexml/document"
|
8
|
-
require "time"
|
9
|
-
|
10
|
-
require "stree/roxy/moxie"
|
11
|
-
require "stree/roxy/proxy"
|
12
|
-
|
13
|
-
require "stree/parser"
|
14
|
-
require "stree/bucket"
|
15
|
-
require "stree/connection"
|
16
|
-
require "stree/exceptions"
|
17
|
-
require "stree/object"
|
18
|
-
require "stree/service"
|
19
|
-
require "stree/signature"
|
20
|
-
|
21
|
-
module Stree
|
22
|
-
# Default (and only) host serving S3 stuff
|
23
|
-
HOST = "s3.amazonaws.com"
|
24
|
-
end
|