s33r 0.5.2 → 0.5.3
Sign up to get free protection for your applications and to get access to all the features.
- data/examples/fores33r/app/controllers/browser_controller.rb +2 -1
- data/examples/fores33r/app/views/browser/_create_bucket.rhtml +2 -2
- data/examples/fores33r/app/views/browser/_upload.rhtml +2 -2
- data/examples/fores33r/config/environment.rb +2 -2
- data/examples/fores33r/config/routes.rb +11 -5
- data/lib/s33r.rb +13 -3
- data/lib/s33r/client.rb +3 -1
- data/lib/s33r/{builder.rb → orderly_xml_markup.rb} +3 -1
- data/lib/s33r/utility.rb +7 -2
- data/test/cases/spec_acl.rb +11 -11
- data/test/cases/spec_bucket_listing.rb +12 -12
- data/test/cases/spec_logging.rb +3 -3
- data/test/cases/spec_s3_object.rb +10 -10
- data/test/cases/spec_utility.rb +46 -39
- data/test/cases/spec_xml.rb +3 -3
- data/test/test_setup.rb +6 -1
- metadata +85 -88
- data/examples/fores33r/log/development.log +0 -3032
- data/examples/fores33r/log/mongrel.log +0 -59
- data/examples/fores33r/tmp/sessions/ruby_sess.75445a6f4154aa9d +0 -0
- data/examples/fores33r/tmp/sessions/ruby_sess.f55f1b0adcf2e2d8 +0 -0
@@ -40,8 +40,9 @@ class BrowserController < ApplicationController
|
|
40
40
|
def delete
|
41
41
|
bucket_name = params[:bucket_name]
|
42
42
|
resource_key = params[:resource_key]
|
43
|
+
|
43
44
|
if resource_key
|
44
|
-
@s3.do_delete(:bucket => bucket_name, :key => resource_key)
|
45
|
+
@s3.do_delete(:bucket => bucket_name, :key => resource_key.to_s)
|
45
46
|
to_url = url_for(:action => 'show_bucket', :bucket_name => bucket_name)
|
46
47
|
notice = "Resource"
|
47
48
|
else
|
@@ -1,6 +1,6 @@
|
|
1
|
-
|
1
|
+
<% form_for '', :url => {:action => 'create_bucket'} do %>
|
2
2
|
<p>Create a new bucket: <%= text_field 'bucket', 'name' %></p>
|
3
3
|
<p>Use your default bucket prefix (<strong><%= @default_prefix %></strong>)?
|
4
4
|
<%= check_box_tag 'bucket[prefix]', 1, true %></p>
|
5
5
|
<p><%= submit_tag 'Create' %></p>
|
6
|
-
|
6
|
+
<% end %>
|
@@ -1,5 +1,5 @@
|
|
1
|
-
|
1
|
+
<% form_for '', :url => {:action => 'upload'}, :html => {:multipart => true} do %>
|
2
2
|
<%= hidden_field 'upload', 'bucket_name', :value => @bucket_name %>
|
3
3
|
<p>Upload a file to this bucket:<br /><%= file_field('upload', 'filename', :size => 20) %></p>
|
4
4
|
<p><%= submit_tag 'Upload' %></p>
|
5
|
-
|
5
|
+
<% end %>
|
@@ -5,7 +5,7 @@
|
|
5
5
|
# ENV['RAILS_ENV'] ||= 'production'
|
6
6
|
|
7
7
|
# Specifies gem version of Rails to use when vendor/rails is not present
|
8
|
-
RAILS_GEM_VERSION = '1.1
|
8
|
+
RAILS_GEM_VERSION = '1.2.1'
|
9
9
|
|
10
10
|
# Bootstrap the Rails environment, frameworks, and default configuration
|
11
11
|
require File.join(File.dirname(__FILE__), 'boot')
|
@@ -63,4 +63,4 @@ config, S3_OPTIONS =
|
|
63
63
|
|
64
64
|
options = config.merge(S3_OPTIONS)
|
65
65
|
|
66
|
-
S3_CLIENT = S33r::Client.new(options)
|
66
|
+
S3_CLIENT = S33r::Client.new(options)
|
@@ -13,11 +13,17 @@ ActionController::Routing::Routes.draw do |map|
|
|
13
13
|
# -- just remember to delete public/index.html.
|
14
14
|
map.connect '', :controller => 'browser'
|
15
15
|
|
16
|
-
|
17
|
-
map.connect '/
|
18
|
-
|
19
|
-
map.connect '/
|
20
|
-
|
16
|
+
bucket = { :bucket_name => /.*/ }
|
17
|
+
map.connect '/show_bucket/:bucket_name', :controller => 'browser', :action => 'show_bucket',
|
18
|
+
:requirements => bucket
|
19
|
+
map.connect '/plain_bucket/:bucket_name/listing.txt', :controller => 'browser', :action => 'plain_bucket',
|
20
|
+
:requirements => bucket
|
21
|
+
map.connect '/add_index/:bucket_name', :controller => 'browser', :action => 'add_index',
|
22
|
+
:requirements => bucket
|
23
|
+
map.connect '/delete/:bucket_name/key/:resource_key', :controller => 'browser', :action => 'delete',
|
24
|
+
:requirements => bucket.merge({:resource_key => /.*/})
|
25
|
+
map.connect '/delete/:bucket_name', :controller => 'browser', :action => 'delete',
|
26
|
+
:requirements => bucket
|
21
27
|
map.connect '/create_bucket', :controller => 'browser', :action => 'create_bucket'
|
22
28
|
|
23
29
|
# Install the default route as the lowest priority.
|
data/lib/s33r.rb
CHANGED
@@ -10,15 +10,25 @@ require 'net/https'
|
|
10
10
|
require 'stringio'
|
11
11
|
|
12
12
|
require 'rubygems'
|
13
|
-
|
13
|
+
|
14
|
+
if respond_to? 'gem'
|
15
|
+
gem 'builder'
|
16
|
+
else
|
17
|
+
require_gem 'builder'
|
18
|
+
end
|
19
|
+
|
14
20
|
|
15
21
|
begin
|
16
22
|
require 'xml/libxml'
|
17
23
|
rescue LoadError
|
18
|
-
|
24
|
+
if respond_to? 'gem'
|
25
|
+
gem 'libxml-ruby'
|
26
|
+
else
|
27
|
+
require_gem 'libxml-ruby'
|
28
|
+
end
|
19
29
|
end
|
20
30
|
|
21
|
-
to_load = ['mimetypes', '
|
31
|
+
to_load = ['mimetypes', 'orderly_xml_markup', 'libxml_extensions', 's33r_http', 'networking',
|
22
32
|
's33r_exception', 'utility', 's3_acl', 's3_logging', 'bucket_listing', 'client', 'bucket', 's3_obj']
|
23
33
|
|
24
34
|
base = File.join(File.dirname(__FILE__), 's33r')
|
data/lib/s33r/client.rb
CHANGED
@@ -211,10 +211,12 @@ module S33r
|
|
211
211
|
# Delete a Bucket.
|
212
212
|
#
|
213
213
|
# +options+:
|
214
|
-
# * <tt>:force => true</tt>: To clear the content of the bucket first.
|
214
|
+
# * <tt>:force => true</tt>: To clear the content of the bucket first. This option adds :escape => true to ensure bucket deletion.
|
215
|
+
# * <tt>:escape => true</tt>: CGI::escape keys when they are appended to the path.
|
215
216
|
def delete_bucket(bucket_name, options={})
|
216
217
|
options[:bucket] = bucket_name
|
217
218
|
if options[:force]
|
219
|
+
options[:escape] = true
|
218
220
|
listing(options).keys.each { |key| do_delete(options.merge(:key => key)) }
|
219
221
|
end
|
220
222
|
do_delete(options).ok?
|
@@ -1,6 +1,8 @@
|
|
1
|
+
require 'builder'
|
2
|
+
|
1
3
|
module S33r
|
2
4
|
# Variant of XmlMarkup which explicitly orders attributes.
|
3
|
-
class OrderlyXmlMarkup < Builder::XmlMarkup
|
5
|
+
class OrderlyXmlMarkup < ::Builder::XmlMarkup
|
4
6
|
|
5
7
|
# Override Builder _insert_attributes so attributes are ordered.
|
6
8
|
def _insert_attributes(attrs, order=[])
|
data/lib/s33r/utility.rb
CHANGED
@@ -281,7 +281,8 @@ module S33r
|
|
281
281
|
str
|
282
282
|
end
|
283
283
|
|
284
|
-
# Returns the path for this bucket and key.
|
284
|
+
# Returns the path for this bucket and key. By default, keys are not CGI-escaped; if you want
|
285
|
+
# escaping, use the <tt>:escape => true</tt> option.
|
285
286
|
#
|
286
287
|
# +options+:
|
287
288
|
# * <tt>:bucket => 'my-bucket'</tt>: get a path which includes the bucket (unless
|
@@ -293,6 +294,7 @@ module S33r
|
|
293
294
|
# * <tt>:subdomain => true</tt>: don't include the bucket name in the path.
|
294
295
|
# * <tt>:acl => true</tt>: append ?acl to the front of the querystring.
|
295
296
|
# * <tt>:logging => true</tt>: append ?logging to the start of the querystring.
|
297
|
+
# * <tt>:escape => true</tt>: CGI::escape keys when they are appended to the path.
|
296
298
|
def s3_path(options={})
|
297
299
|
bucket = options[:bucket]
|
298
300
|
key = options[:key]
|
@@ -308,7 +310,10 @@ module S33r
|
|
308
310
|
|
309
311
|
path = '/'
|
310
312
|
path += (bucket + '/') if bucket and !options[:subdomain]
|
311
|
-
|
313
|
+
if key
|
314
|
+
key = CGI::escape(key) if options[:escape]
|
315
|
+
path += key
|
316
|
+
end
|
312
317
|
path += '?' + qstring unless '' == qstring
|
313
318
|
path
|
314
319
|
end
|
data/test/cases/spec_acl.rb
CHANGED
@@ -42,32 +42,32 @@ context 'S33r ACL functions' do
|
|
42
42
|
end
|
43
43
|
|
44
44
|
specify 'should represent a grant for a CanonicalUser' do
|
45
|
-
clean_xml(@canonical_user_grant.to_xml).should
|
45
|
+
clean_xml(@canonical_user_grant.to_xml).should == @acl_grant_xml1
|
46
46
|
end
|
47
47
|
|
48
48
|
specify 'should represent a grant for an AmazonUserByEmail' do
|
49
|
-
clean_xml(@amazon_grant.to_xml).should
|
49
|
+
clean_xml(@amazon_grant.to_xml).should == @acl_grant_xml2
|
50
50
|
end
|
51
51
|
|
52
52
|
specify 'should represent a grant for AllUsers' do
|
53
|
-
clean_xml(@group_grant.to_xml).should
|
53
|
+
clean_xml(@group_grant.to_xml).should == @acl_grant_xml3
|
54
54
|
end
|
55
55
|
|
56
56
|
specify 'should represent a grant for AuthenticatedUsers' do
|
57
|
-
clean_xml(@group_grant2.to_xml).should
|
57
|
+
clean_xml(@group_grant2.to_xml).should == @acl_grant_xml4
|
58
58
|
end
|
59
59
|
|
60
60
|
specify 'should generate a valid AccessControlPolicy document' do
|
61
|
-
clean_xml(@full_acl_doc.to_xml).should
|
61
|
+
clean_xml(@full_acl_doc.to_xml).should == @full_acl_xml
|
62
62
|
end
|
63
63
|
|
64
64
|
specify 'should provide convenience classes for grants' do
|
65
|
-
clean_xml(@con_full_acl_doc.to_xml).should
|
65
|
+
clean_xml(@con_full_acl_doc.to_xml).should == @full_acl_xml
|
66
66
|
end
|
67
67
|
|
68
68
|
specify 'needs equality method for grantees' do
|
69
69
|
test_grantee = Group.new(:all_users)
|
70
|
-
test_grantee.should
|
70
|
+
test_grantee.should == @group_grantee
|
71
71
|
test_grantee.should.not.equal @amazon_grantee
|
72
72
|
end
|
73
73
|
|
@@ -82,7 +82,7 @@ context 'S33r ACL functions' do
|
|
82
82
|
"</Grantee>"
|
83
83
|
doc = XML.get_xml_doc(xml)
|
84
84
|
grantee = Grantee.from_xml(doc)
|
85
|
-
grantee.should
|
85
|
+
grantee.should == @amazon_grantee
|
86
86
|
end
|
87
87
|
|
88
88
|
specify 'should correctly create Group grantee from XML node' do
|
@@ -91,7 +91,7 @@ context 'S33r ACL functions' do
|
|
91
91
|
"</Grantee>"
|
92
92
|
doc = XML.get_xml_doc(xml)
|
93
93
|
grantee = Grantee.from_xml(doc)
|
94
|
-
grantee.should
|
94
|
+
grantee.should == @group_grantee
|
95
95
|
end
|
96
96
|
|
97
97
|
specify 'should correctly create Group grantee for AuthenticatedUsers from XML node' do
|
@@ -100,14 +100,14 @@ context 'S33r ACL functions' do
|
|
100
100
|
"</Grantee>"
|
101
101
|
doc = XML.get_xml_doc(xml)
|
102
102
|
grantee = Grantee.from_xml(doc)
|
103
|
-
grantee.should
|
103
|
+
grantee.should == @group_grantee2
|
104
104
|
p grantee.group_type
|
105
105
|
p @group_grantee2.group_type
|
106
106
|
end
|
107
107
|
|
108
108
|
specify 'should parse AccessControlPolicy documents' do
|
109
109
|
acl_doc_from_xml = Policy.from_xml(@full_acl_xml)
|
110
|
-
acl_doc_from_xml.owner.should
|
110
|
+
acl_doc_from_xml.owner.should == @full_acl_doc.owner
|
111
111
|
@full_acl_doc.grants.each do |g|
|
112
112
|
acl_doc_from_xml.grants = acl_doc_from_xml.grants.delete_if { |i| i == g }
|
113
113
|
end
|
@@ -35,22 +35,22 @@ context 'S33r bucket listing' do
|
|
35
35
|
end
|
36
36
|
|
37
37
|
specify 'should present bucket metadata as typed properties' do
|
38
|
-
@bucket_listing.name.should
|
39
|
-
@bucket_listing.prefix.should
|
40
|
-
@bucket_listing.marker.should
|
41
|
-
@bucket_listing.max_keys.should
|
42
|
-
@bucket_listing.is_truncated.should
|
38
|
+
@bucket_listing.name.should ==('testingtesting')
|
39
|
+
@bucket_listing.prefix.should ==('')
|
40
|
+
@bucket_listing.marker.should ==('')
|
41
|
+
@bucket_listing.max_keys.should ==(1000)
|
42
|
+
@bucket_listing.is_truncated.should ==(false)
|
43
43
|
@bucket_listing.delimiter.should.be nil
|
44
44
|
end
|
45
45
|
|
46
46
|
specify 'when listing XML is reset, should update all properties correctly' do
|
47
47
|
@bucket_listing.set_listing_xml(@with_bucket_listing_xml2)
|
48
|
-
@bucket_listing.name.should
|
49
|
-
@bucket_listing.prefix.should
|
50
|
-
@bucket_listing.marker.should
|
51
|
-
@bucket_listing.max_keys.should
|
52
|
-
@bucket_listing.delimiter.should
|
53
|
-
@bucket_listing.is_truncated.should
|
48
|
+
@bucket_listing.name.should ==('testing2')
|
49
|
+
@bucket_listing.prefix.should ==('/home/ell/')
|
50
|
+
@bucket_listing.marker.should ==('')
|
51
|
+
@bucket_listing.max_keys.should ==(100)
|
52
|
+
@bucket_listing.delimiter.should ==('/')
|
53
|
+
@bucket_listing.is_truncated.should ==(false)
|
54
54
|
end
|
55
55
|
|
56
56
|
specify 'should provide private setters for metadata' do
|
@@ -59,7 +59,7 @@ context 'S33r bucket listing' do
|
|
59
59
|
# names of the setters
|
60
60
|
setters = @bucket_property_setters
|
61
61
|
# all methods should be a superset of the private setters
|
62
|
-
methods.superset?(setters.to_set).should
|
62
|
+
methods.superset?(setters.to_set).should == true
|
63
63
|
end
|
64
64
|
|
65
65
|
specify 'should store resources (<Contents> elements) in a hash' do
|
data/test/cases/spec_logging.rb
CHANGED
@@ -21,11 +21,11 @@ context 'S33r logging' do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
specify 'should generate BucketLoggingStatus XML document to enable logging' do
|
24
|
-
clean_xml(@logging_resource_to_enable.to_xml).should
|
24
|
+
clean_xml(@logging_resource_to_enable.to_xml).should == @logging_enabled_xml
|
25
25
|
end
|
26
26
|
|
27
27
|
specify 'should generate BucketLoggingStatus XML document to disable logging' do
|
28
|
-
clean_xml(@logging_resource_to_disable.to_xml).should
|
28
|
+
clean_xml(@logging_resource_to_disable.to_xml).should == @logging_disabled_xml
|
29
29
|
end
|
30
30
|
|
31
31
|
specify 'should represent LogDelivery grants so buckets can act as logging targets' do
|
@@ -42,6 +42,6 @@ context 'S33r logging' do
|
|
42
42
|
|
43
43
|
specify 'should be able to simply add logging target grants to an ACL' do
|
44
44
|
@logging_acl_doc_no_grants.add_log_target_grants
|
45
|
-
clean_xml(@logging_acl_doc_no_grants.to_xml).should
|
45
|
+
clean_xml(@logging_acl_doc_no_grants.to_xml).should == @logging_acl_xml
|
46
46
|
end
|
47
47
|
end
|
@@ -23,15 +23,15 @@ context 'S3 object' do
|
|
23
23
|
end
|
24
24
|
|
25
25
|
specify 'can be initialised from XML fragment with correct data types' do
|
26
|
-
@s3obj.key.should
|
26
|
+
@s3obj.key.should == '/home/ell/dir1/four.txt'
|
27
27
|
d = @s3obj.last_modified
|
28
|
-
[d.year, d.month, d.day, d.hour, d.min, d.sec].should
|
29
|
-
@s3obj.etag.should
|
30
|
-
@s3obj.size.should
|
28
|
+
[d.year, d.month, d.day, d.hour, d.min, d.sec].should == [2006, 8, 19, 22, 53, 29]
|
29
|
+
@s3obj.etag.should == '24ce59274b89287b3960c184153ac24b'
|
30
|
+
@s3obj.size.should == 14
|
31
31
|
end
|
32
32
|
|
33
33
|
specify 'can be associated with bucket on creation' do
|
34
|
-
@s3obj2.bucket.name.should
|
34
|
+
@s3obj2.bucket.name.should == 'quotes'
|
35
35
|
end
|
36
36
|
|
37
37
|
specify 'can be created from a file' do
|
@@ -39,7 +39,7 @@ context 'S3 object' do
|
|
39
39
|
end
|
40
40
|
|
41
41
|
specify 'should treat the owner as an object in his/her own right' do
|
42
|
-
[@s3obj.owner.user_id, @s3obj.owner.display_name].should
|
42
|
+
[@s3obj.owner.user_id, @s3obj.owner.display_name].should == \
|
43
43
|
['56efddfead5aa65da942f156fb2b294f44d78fd932d701331edc5fba19620fd4', 'elliotsmith3']
|
44
44
|
@s3obj.owner.should_be_instance_of S3ACL::CanonicalUser
|
45
45
|
end
|
@@ -57,18 +57,18 @@ context 'S3 object' do
|
|
57
57
|
end
|
58
58
|
|
59
59
|
specify 'should return authenticated URL' do
|
60
|
-
@s3obj2.url(:authenticated => true, :expires => 1141889120).should
|
60
|
+
@s3obj2.url(:authenticated => true, :expires => 1141889120).should == @correct_authenticated_url
|
61
61
|
end
|
62
62
|
|
63
63
|
specify 'should return public URL' do
|
64
|
-
@s3obj2.url.should
|
64
|
+
@s3obj2.url.should == @correct_public_url
|
65
65
|
end
|
66
66
|
|
67
67
|
specify 'should optionally return HTTPS URL' do
|
68
|
-
@s3obj2.url(:use_ssl => true).should
|
68
|
+
@s3obj2.url(:use_ssl => true).should == @correct_public_url_with_ssl
|
69
69
|
end
|
70
70
|
|
71
71
|
specify 'should optionally return URL with domain name set to bucket name' do
|
72
|
-
@s3obj2.url(:subdomain => true).should
|
72
|
+
@s3obj2.url(:subdomain => true).should == @correct_public_url_with_subdomain
|
73
73
|
end
|
74
74
|
end
|
data/test/cases/spec_utility.rb
CHANGED
@@ -45,38 +45,40 @@ context 'S33r utility' do
|
|
45
45
|
@correct_acl_url = "http://s3.amazonaws.com/quotes/?acl"
|
46
46
|
@correct_acl_url_with_key = "http://s3.amazonaws.com/quotes/nelson?acl"
|
47
47
|
@correct_public_url_with_qstring = "http://s3.amazonaws.com/quotes/?prefix=%2Fhome&max-keys=400"
|
48
|
+
@url_with_escaped_key = "http://s3.amazonaws.com/quotes/some+key"
|
49
|
+
@url_with_unescaped_key = "http://s3.amazonaws.com/quotes/some key"
|
48
50
|
end
|
49
51
|
|
50
52
|
specify 'should load config files containing standard S33r settings' do
|
51
53
|
config, _ = S33r.load_config(@yaml_file)
|
52
|
-
config[:access].should
|
54
|
+
config[:access].should == Testing::ACCESS_KEY
|
53
55
|
end
|
54
56
|
|
55
57
|
specify 'can parse ERb embedded in config. file' do
|
56
58
|
config, _ = S33r.load_config(@yaml_file)
|
57
|
-
config[:secret].should
|
59
|
+
config[:secret].should == Testing::SECRET_ACCESS_KEY
|
58
60
|
end
|
59
61
|
|
60
62
|
specify 'can parse extra application-specific settings in config. file' do
|
61
63
|
config, options = S33r.load_config(@yaml_file)
|
62
|
-
options[:email_to].should
|
64
|
+
options[:email_to].should == Testing::EMAIL
|
63
65
|
# Make sure the 'options' section has not been included in the general config..
|
64
66
|
config.keys.should.not.include :options
|
65
67
|
end
|
66
68
|
|
67
69
|
specify 'should generate correct canonical strings' do
|
68
70
|
generate_canonical_string(@for_request_method, @for_request_path,
|
69
|
-
@for_request_headers).should
|
71
|
+
@for_request_headers).should == @correct_canonical_string
|
70
72
|
end
|
71
73
|
|
72
74
|
specify 'should generate correct signatures' do
|
73
75
|
generate_signature(Testing::SECRET_ACCESS_KEY,
|
74
|
-
@correct_canonical_string).should
|
76
|
+
@correct_canonical_string).should == @correct_signature
|
75
77
|
end
|
76
78
|
|
77
79
|
specify 'should generate correct auth headers' do
|
78
80
|
generate_auth_header_value(@for_request_method, @for_request_path, @for_request_headers,
|
79
|
-
Testing::ACCESS_KEY, Testing::SECRET_ACCESS_KEY).should
|
81
|
+
Testing::ACCESS_KEY, Testing::SECRET_ACCESS_KEY).should == @correct_auth_header
|
80
82
|
end
|
81
83
|
|
82
84
|
specify 'should not generate auth header if bad HTTP method passed' do
|
@@ -95,8 +97,8 @@ context 'S33r utility' do
|
|
95
97
|
fixed_headers = default_headers(@for_incomplete_headers, :date => now,
|
96
98
|
:content_type => 'text/html')
|
97
99
|
|
98
|
-
fixed_headers['Date'].should
|
99
|
-
fixed_headers['Content-Type'].should
|
100
|
+
fixed_headers['Date'].should == now.httpdate
|
101
|
+
fixed_headers['Content-Type'].should == 'text/html'
|
100
102
|
end
|
101
103
|
|
102
104
|
specify 'should generate correct x-amz-meta- headers from a hash' do
|
@@ -104,8 +106,8 @@ context 'S33r utility' do
|
|
104
106
|
headers = metadata_headers(meta)
|
105
107
|
headers.should.include 'x-amz-meta-myname'
|
106
108
|
headers.should.include 'x-amz-meta-myage'
|
107
|
-
headers['x-amz-meta-myname'].should
|
108
|
-
headers['x-amz-meta-myage'].should
|
109
|
+
headers['x-amz-meta-myname'].should == 'elliot'
|
110
|
+
headers['x-amz-meta-myage'].should == '36'
|
109
111
|
end
|
110
112
|
|
111
113
|
specify 'should not generate canned ACL header if invalid canned ACL supplied' do
|
@@ -117,28 +119,28 @@ context 'S33r utility' do
|
|
117
119
|
new_headers = canned_acl_header('private')
|
118
120
|
new_headers.should.have(1).keys
|
119
121
|
new_headers.keys.should.include 'x-amz-acl'
|
120
|
-
new_headers['x-amz-acl'].should
|
122
|
+
new_headers['x-amz-acl'].should == 'private'
|
121
123
|
end
|
122
124
|
|
123
125
|
specify 'should set sensible defaults for missing Content-Type and Date headers' do
|
124
126
|
fixed_headers = default_headers(@for_incomplete_headers)
|
125
|
-
fixed_headers['Content-Type'].should
|
127
|
+
fixed_headers['Content-Type'].should == ''
|
126
128
|
fixed_headers.include?('Date').should.not.be nil
|
127
129
|
end
|
128
130
|
|
129
131
|
specify 'should default to text/plain mimetype for unknown file types' do
|
130
|
-
guess_mime_type('hello.madeup').should
|
132
|
+
guess_mime_type('hello.madeup').should ==('text/plain')
|
131
133
|
end
|
132
134
|
|
133
135
|
specify 'should generate correct Content-Disposition, Content-Type and Content-Transfer-Encoding headers' do
|
134
136
|
headers = content_headers('text/plain', 'download.jpg', true)
|
135
|
-
headers['Content-Type'].should
|
136
|
-
headers['Content-Disposition'].should
|
137
|
+
headers['Content-Type'].should == 'text/plain'
|
138
|
+
headers['Content-Disposition'].should == "attachment; filename=download.jpg"
|
137
139
|
|
138
140
|
headers = content_headers('image/jpeg', '/home/you/me.jpg', true)
|
139
|
-
headers['Content-Type'].should
|
140
|
-
headers['Content-Transfer-Encoding'].should
|
141
|
-
headers['Content-Disposition'].should
|
141
|
+
headers['Content-Type'].should == 'image/jpeg'
|
142
|
+
headers['Content-Transfer-Encoding'].should == 'binary'
|
143
|
+
headers['Content-Disposition'].should == "attachment; filename=me.jpg"
|
142
144
|
end
|
143
145
|
|
144
146
|
specify 'should recognise invalid bucket names' do
|
@@ -149,75 +151,75 @@ context 'S33r utility' do
|
|
149
151
|
end
|
150
152
|
|
151
153
|
specify 'should return empty string if generating querystring with no key/value pairs' do
|
152
|
-
generate_querystring({}).
|
154
|
+
generate_querystring({}).should == ''
|
153
155
|
end
|
154
156
|
|
155
157
|
specify 'should correctly format querystring key/value pairs' do
|
156
|
-
generate_querystring({'message' => 'Hello world', 'id' => 1, 'page' => '[2,4]'}).
|
158
|
+
generate_querystring({'message' => 'Hello world', 'id' => 1, 'page' => '[2,4]'}).should == \
|
157
159
|
'message=Hello+world&id=1&page=%5B2%2C4%5D'
|
158
160
|
end
|
159
161
|
|
160
162
|
specify 'should allow symbols as names for querystring variables when generating querystrings' do
|
161
|
-
generate_querystring({ :prefix => '/home/ell' }).should
|
163
|
+
generate_querystring({ :prefix => '/home/ell' }).should ==('prefix=%2Fhome%2Fell')
|
162
164
|
end
|
163
165
|
|
164
166
|
specify 'should convert integers to strings when generating querystrings' do
|
165
|
-
generate_querystring({ 'max-keys' => 400 }).should
|
167
|
+
generate_querystring({ 'max-keys' => 400 }).should ==('max-keys=400')
|
166
168
|
end
|
167
169
|
|
168
170
|
specify 'should generate URLs with authentication parameters' do
|
169
171
|
s3_authenticated_url(Testing::ACCESS_KEY, Testing::SECRET_ACCESS_KEY, :bucket => 'quotes', \
|
170
|
-
:key => 'nelson', :expires => 1141889120).should
|
172
|
+
:key => 'nelson', :expires => 1141889120).should == @correct_authenticated_url
|
171
173
|
end
|
172
174
|
|
173
175
|
specify 'should be able to pass credentials as an option to the basic URL generator' do
|
174
176
|
s3_url(:access => Testing::ACCESS_KEY, :secret => Testing::SECRET_ACCESS_KEY, \
|
175
177
|
:authenticated => true, :bucket => 'quotes', :key => 'nelson', \
|
176
|
-
:expires => 1141889120).should
|
178
|
+
:expires => 1141889120).should == @correct_authenticated_url
|
177
179
|
end
|
178
180
|
|
179
181
|
specify 'should generate correct public URLs' do
|
180
|
-
s3_public_url(:bucket => 'quotes', :key => 'nelson').should
|
182
|
+
s3_public_url(:bucket => 'quotes', :key => 'nelson').should == @correct_public_url
|
181
183
|
end
|
182
184
|
|
183
185
|
specify 'should correctly append querystring variables' do
|
184
|
-
s3_url(:bucket => 'quotes', :querystring => {'max-keys' => 400, 'prefix' => '/home'}).should
|
186
|
+
s3_url(:bucket => 'quotes', :querystring => {'max-keys' => 400, 'prefix' => '/home'}).should == \
|
185
187
|
@correct_public_url_with_qstring
|
186
188
|
end
|
187
189
|
|
188
190
|
specify 'should generate HTTPS URLs' do
|
189
|
-
s3_public_url(:bucket => 'quotes', :key => 'nelson', :use_ssl => true).should
|
191
|
+
s3_public_url(:bucket => 'quotes', :key => 'nelson', :use_ssl => true).should == @correct_public_ssl_url
|
190
192
|
end
|
191
193
|
|
192
194
|
specify 'should generate public URLs with bucket name as subdomain' do
|
193
|
-
s3_public_url(:bucket => 'quotes', :key => 'nelson', :subdomain => true).should
|
195
|
+
s3_public_url(:bucket => 'quotes', :key => 'nelson', :subdomain => true).should == \
|
194
196
|
@correct_public_url_with_subdomain
|
195
|
-
s3_public_url(:bucket => 'quotes', :key => 'nelson', :subdomain => true, :use_ssl => true).should
|
197
|
+
s3_public_url(:bucket => 'quotes', :key => 'nelson', :subdomain => true, :use_ssl => true).should == \
|
196
198
|
@correct_public_url_with_ssl_and_subdomain
|
197
199
|
end
|
198
200
|
|
199
201
|
specify 'should generate URLs for buckets without keys' do
|
200
|
-
s3_public_url(:bucket => 'quotes').should
|
202
|
+
s3_public_url(:bucket => 'quotes').should == @correct_public_url_without_key
|
201
203
|
end
|
202
204
|
|
203
205
|
specify 'should generate logging URLs' do
|
204
|
-
s3_url(:bucket => 'quotes', :logging => true).should
|
206
|
+
s3_url(:bucket => 'quotes', :logging => true).should == @correct_logging_url
|
205
207
|
end
|
206
208
|
|
207
209
|
specify 'should generate ACL URLs' do
|
208
|
-
s3_url(:bucket => 'quotes', :acl => true).should
|
209
|
-
s3_url(:bucket => 'quotes', :key => 'nelson', :acl => true).should
|
210
|
+
s3_url(:bucket => 'quotes', :acl => true).should == @correct_acl_url
|
211
|
+
s3_url(:bucket => 'quotes', :key => 'nelson', :acl => true).should == @correct_acl_url_with_key
|
210
212
|
end
|
211
213
|
|
212
214
|
specify 'should turn off subdomain if authenticated URL' do
|
213
215
|
s3_url(:access => Testing::ACCESS_KEY, :secret => Testing::SECRET_ACCESS_KEY, \
|
214
216
|
:authenticated => true, :bucket => 'quotes', :key => 'nelson', :subdomain => true, \
|
215
|
-
:expires => 1141889120).should
|
217
|
+
:expires => 1141889120).should == @correct_authenticated_url
|
216
218
|
end
|
217
219
|
|
218
220
|
specify 'should turn off subdomain if generating SSL URL' do
|
219
221
|
s3_url(:bucket => 'quotes', :key => 'nelson', :use_ssl => true, \
|
220
|
-
:subdomain => true).should
|
222
|
+
:subdomain => true).should == @correct_public_ssl_url
|
221
223
|
end
|
222
224
|
|
223
225
|
specify 'should produce correct default expiry time if none specified, or time 50 years \
|
@@ -231,14 +233,14 @@ context 'S33r utility' do
|
|
231
233
|
# Default to DEFAULT_EXPIRY_SECS from now
|
232
234
|
expected_expiry = Time.now.to_i + DEFAULT_EXPIRY_SECS
|
233
235
|
expires = S33r.parse_expiry
|
234
|
-
expires.should
|
236
|
+
expires.should == expected_expiry
|
235
237
|
expires.should_be_kind_of Integer
|
236
238
|
|
237
239
|
# If :far_flung_future is passed, default to 20 years from now.
|
238
240
|
expected_expiry = Time.now.to_i +
|
239
241
|
(60 * 60 * 24 * 365.25 * 20).to_i
|
240
242
|
expires = S33r.parse_expiry(:far_flung_future)
|
241
|
-
expires.should
|
243
|
+
expires.should == expected_expiry
|
242
244
|
expires.should_be_kind_of Integer
|
243
245
|
|
244
246
|
class Time
|
@@ -251,14 +253,19 @@ context 'S33r utility' do
|
|
251
253
|
datetime_str = '9th January 2007 13:33'
|
252
254
|
expected_expiry = Time.parse(datetime_str).to_i
|
253
255
|
expires = S33r.parse_expiry(datetime_str)
|
254
|
-
expires.should
|
256
|
+
expires.should == expected_expiry
|
255
257
|
expires.should_be_kind_of Integer
|
256
258
|
end
|
257
259
|
|
258
260
|
specify 'should provide a method for converting string keys of a hash into symbols' do
|
259
261
|
h = {'access' => Testing::ACCESS_KEY, 'secret' => Testing::SECRET_ACCESS_KEY}
|
260
262
|
symbolised = S33r.keys_to_symbols(h)
|
261
|
-
symbolised.should
|
263
|
+
symbolised.should ==({:access => Testing::ACCESS_KEY, :secret => Testing::SECRET_ACCESS_KEY})
|
264
|
+
end
|
265
|
+
|
266
|
+
specify 'can optionally escape keys passed in paths' do
|
267
|
+
s3_url(:bucket => 'quotes', :key => 'some key', :escape => true).should == @url_with_escaped_key
|
268
|
+
s3_url(:bucket => 'quotes', :key => 'some key').should == @url_with_unescaped_key
|
262
269
|
end
|
263
270
|
|
264
271
|
end
|