s3 0.2.0 → 0.2.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 +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
|