uber-s3 0.1.2 → 0.1.3
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/lib/uber-s3/connection/net_http.rb +15 -2
- data/lib/uber-s3/connection.rb +0 -4
- data/lib/uber-s3/object.rb +25 -36
- data/lib/uber-s3/operation/object/access_policy.rb +9 -0
- data/lib/uber-s3/operation/object/cache_control.rb +1 -0
- data/lib/uber-s3/operation/object/content_disposition.rb +1 -0
- data/lib/uber-s3/operation/object/content_encoding.rb +45 -0
- data/lib/uber-s3/operation/object/content_md5.rb +1 -0
- data/lib/uber-s3/operation/object/content_type.rb +9 -0
- data/lib/uber-s3/operation/object/expires.rb +1 -0
- data/lib/uber-s3/operation/object/storage_class.rb +10 -0
- data/lib/uber-s3/operation.rb +26 -13
- data/lib/uber-s3/version.rb +1 -1
- data/lib/uber-s3.rb +3 -0
- metadata +7 -7
@@ -4,18 +4,31 @@ module UberS3::Connection
|
|
4
4
|
class NetHttp < Adapter
|
5
5
|
|
6
6
|
def request(verb, url, headers={}, body=nil)
|
7
|
+
if verb == :get
|
8
|
+
# Support fetching compressed data
|
9
|
+
headers['Accept-Encoding'] = 'gzip, deflate'
|
10
|
+
end
|
11
|
+
|
7
12
|
uri = URI.parse(url)
|
8
13
|
http = Net::HTTP.new(uri.host, uri.port)
|
9
14
|
|
10
15
|
req_klass = instance_eval("Net::HTTP::"+verb.to_s.capitalize)
|
11
16
|
req = req_klass.new(uri.to_s, headers)
|
12
|
-
|
17
|
+
|
13
18
|
r = http.request(req, body)
|
14
19
|
|
20
|
+
# Auto-decode any gzipped objects
|
21
|
+
if verb == :get && r.header['content-encoding'] == 'gzip'
|
22
|
+
gz = Zlib::GzipReader.new(StringIO.new(r.body))
|
23
|
+
response_body = gz.read
|
24
|
+
else
|
25
|
+
response_body = r.body
|
26
|
+
end
|
27
|
+
|
15
28
|
{
|
16
29
|
:status => r.code.to_i,
|
17
30
|
:header => r.header.to_hash,
|
18
|
-
:body =>
|
31
|
+
:body => response_body,
|
19
32
|
:raw => r
|
20
33
|
}
|
21
34
|
end
|
data/lib/uber-s3/connection.rb
CHANGED
@@ -39,10 +39,6 @@ class UberS3
|
|
39
39
|
# headers['Connection'] = (persistent ? 'keep-alive' : 'close')
|
40
40
|
|
41
41
|
if body
|
42
|
-
mime_type = MIME::Types.type_for(path).first
|
43
|
-
|
44
|
-
headers['Content-Type'] ||= mime_type.content_type if mime_type
|
45
|
-
headers['Content-Type'] ||= 'binary/octet-stream'
|
46
42
|
headers['Content-Length'] ||= body.bytesize.to_s
|
47
43
|
end
|
48
44
|
|
data/lib/uber-s3/object.rb
CHANGED
@@ -1,24 +1,28 @@
|
|
1
1
|
class UberS3
|
2
2
|
class Object
|
3
|
+
include Operation::Object::All
|
3
4
|
|
4
|
-
attr_accessor :bucket, :key, :value, :errors
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
:storage_class
|
5
|
+
attr_accessor :bucket, :key, :value, :size, :errors
|
6
|
+
|
7
|
+
# attr_accessor :access,
|
8
|
+
# :cache_control,
|
9
|
+
# :content_disposition,
|
10
|
+
# :content_encoding,
|
11
|
+
# :size,
|
12
|
+
# :content_md5,
|
13
|
+
# :content_type,
|
14
|
+
# :expires,
|
15
|
+
# :storage_class
|
16
16
|
|
17
17
|
def initialize(bucket, key, value=nil, options={})
|
18
|
-
self.bucket
|
19
|
-
self.key
|
20
|
-
self.value
|
18
|
+
self.bucket = bucket
|
19
|
+
self.key = key
|
20
|
+
self.value = value
|
21
|
+
|
22
|
+
# Init state of object
|
23
|
+
infer_content_type!
|
21
24
|
|
25
|
+
# Call operation methods based on options passed
|
22
26
|
bucket.connection.defaults.merge(options).each {|k,v| self.send((k.to_s+'=').to_sym, v) }
|
23
27
|
end
|
24
28
|
|
@@ -38,6 +42,9 @@ class UberS3
|
|
38
42
|
def save
|
39
43
|
headers = {}
|
40
44
|
|
45
|
+
# Encode data if necessary
|
46
|
+
gzip_content!
|
47
|
+
|
41
48
|
# Standard pass through values
|
42
49
|
headers['Cache-Control'] = cache_control
|
43
50
|
headers['Content-Disposition'] = content_disposition
|
@@ -69,6 +76,7 @@ class UberS3
|
|
69
76
|
response = bucket.connection.put(key, headers, value)
|
70
77
|
|
71
78
|
if response[:status] != 200
|
79
|
+
# TODO: .. we should raise stuff here!!!!!!!! exception handling....................
|
72
80
|
self.errors = response[:body]
|
73
81
|
else
|
74
82
|
self.errors = nil
|
@@ -98,32 +106,13 @@ class UberS3
|
|
98
106
|
@key = key.gsub(/^\//,'')
|
99
107
|
end
|
100
108
|
|
101
|
-
##########################
|
102
|
-
|
103
109
|
def value=(value)
|
104
110
|
self.size = value.to_s.bytesize
|
105
111
|
@value = value
|
106
112
|
end
|
107
113
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
if valid_values.include?(access)
|
112
|
-
@access = access
|
113
|
-
else
|
114
|
-
raise "Invalid access value"
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
def storage_class=(storage_class)
|
119
|
-
valid_values = [:standard, :reduced_redundancy]
|
120
|
-
|
121
|
-
if valid_values.include?(storage_class)
|
122
|
-
@storage_class = storage_class
|
123
|
-
else
|
124
|
-
raise "Invalid storage_class value"
|
125
|
-
end
|
126
|
-
end
|
114
|
+
# TODO..
|
115
|
+
# Add callback support so Operations can hook into that ... cleaner. ie. on_save { ... }
|
127
116
|
|
128
117
|
end
|
129
118
|
end
|
@@ -14,6 +14,15 @@ module UberS3::Operation::Object
|
|
14
14
|
end
|
15
15
|
|
16
16
|
module InstanceMethods
|
17
|
+
def access=(access)
|
18
|
+
valid_values = [:private, :public_read, :public_read_write, :authenticated_read]
|
19
|
+
|
20
|
+
if valid_values.include?(access)
|
21
|
+
@access = access
|
22
|
+
else
|
23
|
+
raise "Invalid access value"
|
24
|
+
end
|
25
|
+
end
|
17
26
|
end
|
18
27
|
|
19
28
|
end
|
@@ -6,6 +6,7 @@ module UberS3::Operation::Object
|
|
6
6
|
base.send :include, InstanceMethods
|
7
7
|
|
8
8
|
base.instance_eval do
|
9
|
+
attr_accessor :gzip, :content_encoding
|
9
10
|
end
|
10
11
|
end
|
11
12
|
|
@@ -13,6 +14,50 @@ module UberS3::Operation::Object
|
|
13
14
|
end
|
14
15
|
|
15
16
|
module InstanceMethods
|
17
|
+
|
18
|
+
# Default mime-types to be auto-gzipped if gzip == :web
|
19
|
+
WEB_GZIP_TYPES = ['text/html', 'text/plain', 'text/css',
|
20
|
+
'application/javascript', 'application/x-javascript',
|
21
|
+
'text/xml', 'application/xml', 'application/xml+rss']
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def gzip_content!
|
26
|
+
return if gzip.nil?
|
27
|
+
|
28
|
+
if gzip == true
|
29
|
+
encode = true
|
30
|
+
elsif gzip == :web && WEB_GZIP_TYPES.include?(content_type)
|
31
|
+
encode = true
|
32
|
+
elsif gzip.is_a?(String) && gzip == content_type
|
33
|
+
encode = true
|
34
|
+
elsif gzip.is_a?(Array) && gzip.include?(content_type)
|
35
|
+
encode = true
|
36
|
+
else
|
37
|
+
encode = false
|
38
|
+
end
|
39
|
+
|
40
|
+
if encode
|
41
|
+
self.value = gzip_encoder(value)
|
42
|
+
self.content_encoding = 'gzip'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def gzip_encoder(data)
|
47
|
+
begin
|
48
|
+
gz_stream = StringIO.new
|
49
|
+
gz = Zlib::GzipWriter.new(gz_stream)
|
50
|
+
gz.write(value)
|
51
|
+
gz.close
|
52
|
+
|
53
|
+
gz_stream.string
|
54
|
+
rescue => ex
|
55
|
+
# TODO ...
|
56
|
+
$stderr.puts "Gzip failed: #{ex.message}"
|
57
|
+
raise ex
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
16
61
|
end
|
17
62
|
|
18
63
|
end
|
@@ -6,6 +6,7 @@ module UberS3::Operation::Object
|
|
6
6
|
base.send :include, InstanceMethods
|
7
7
|
|
8
8
|
base.instance_eval do
|
9
|
+
attr_accessor :content_type
|
9
10
|
end
|
10
11
|
end
|
11
12
|
|
@@ -13,6 +14,14 @@ module UberS3::Operation::Object
|
|
13
14
|
end
|
14
15
|
|
15
16
|
module InstanceMethods
|
17
|
+
|
18
|
+
def infer_content_type!
|
19
|
+
mime_type = MIME::Types.type_for(key).first
|
20
|
+
|
21
|
+
self.content_type ||= mime_type.content_type if mime_type
|
22
|
+
self.content_type ||= 'binary/octet-stream'
|
23
|
+
end
|
24
|
+
|
16
25
|
end
|
17
26
|
|
18
27
|
end
|
@@ -6,6 +6,7 @@ module UberS3::Operation::Object
|
|
6
6
|
base.send :include, InstanceMethods
|
7
7
|
|
8
8
|
base.instance_eval do
|
9
|
+
attr_accessor :storage_class
|
9
10
|
end
|
10
11
|
end
|
11
12
|
|
@@ -13,6 +14,15 @@ module UberS3::Operation::Object
|
|
13
14
|
end
|
14
15
|
|
15
16
|
module InstanceMethods
|
17
|
+
def storage_class=(storage_class)
|
18
|
+
valid_values = [:standard, :reduced_redundancy]
|
19
|
+
|
20
|
+
if valid_values.include?(storage_class)
|
21
|
+
@storage_class = storage_class
|
22
|
+
else
|
23
|
+
raise "Invalid storage_class value"
|
24
|
+
end
|
25
|
+
end
|
16
26
|
end
|
17
27
|
|
18
28
|
end
|
data/lib/uber-s3/operation.rb
CHANGED
@@ -1,22 +1,35 @@
|
|
1
1
|
class UberS3
|
2
2
|
module Operation
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
module Bucket
|
5
|
+
module All
|
6
|
+
def self.included(base)
|
7
|
+
Operation.include_modules(base, 'bucket')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module Object
|
13
|
+
module All
|
14
|
+
def self.included(base)
|
15
|
+
Operation.include_modules(base, 'object')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def include_modules(base, path)
|
21
|
+
# Auto include modules of a particular path
|
22
|
+
Dir[File.dirname(__FILE__)+"/operation/#{path}/*.rb"].each do |op|
|
23
|
+
group_module_name = self.to_s + '::' + path.split('_').map {|x| x.capitalize}.join("")
|
24
|
+
op_klass_name = File.basename(op).gsub(/.rb$/i, '').split('_').map {|x| x.capitalize}.join("")
|
25
|
+
|
11
26
|
require op
|
12
|
-
op_klass = instance_eval(
|
13
|
-
|
14
|
-
|
15
|
-
group_klass.send :include, op_klass
|
27
|
+
op_klass = instance_eval(group_module_name+'::'+op_klass_name)
|
28
|
+
|
29
|
+
base.send :include, op_klass
|
16
30
|
end
|
17
31
|
end
|
32
|
+
module_function :include_modules
|
18
33
|
|
19
34
|
end
|
20
35
|
end
|
21
|
-
|
22
|
-
|
data/lib/uber-s3/version.rb
CHANGED
data/lib/uber-s3.rb
CHANGED
@@ -4,6 +4,8 @@ require 'openssl'
|
|
4
4
|
require 'forwardable'
|
5
5
|
require 'base64'
|
6
6
|
require 'digest/md5'
|
7
|
+
require 'zlib'
|
8
|
+
require 'stringio'
|
7
9
|
require 'mime/types'
|
8
10
|
|
9
11
|
class UberS3
|
@@ -30,6 +32,7 @@ require 'uber-s3/version'
|
|
30
32
|
require 'uber-s3/exceptions'
|
31
33
|
require 'uber-s3/connection'
|
32
34
|
require 'uber-s3/authorization'
|
35
|
+
require 'uber-s3/operation'
|
33
36
|
require 'uber-s3/bucket'
|
34
37
|
require 'uber-s3/object'
|
35
38
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uber-s3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2011-10-17 00:00:00.000000000Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mime-types
|
16
|
-
requirement: &
|
16
|
+
requirement: &70300780746280 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '1.16'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70300780746280
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rake
|
27
|
-
requirement: &
|
27
|
+
requirement: &70300780745880 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70300780745880
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rspec
|
38
|
-
requirement: &
|
38
|
+
requirement: &70300780745320 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: 2.7.0
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70300780745320
|
47
47
|
description: A simple & very fast S3 client supporting sync and async communication
|
48
48
|
email:
|
49
49
|
- peter@nulayer.com
|