uber-s3 0.1.3 → 0.1.4
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/bucket.rb +7 -10
- data/lib/uber-s3/connection/em_http.rb +2 -3
- data/lib/uber-s3/connection/em_http_fibered.rb +2 -2
- data/lib/uber-s3/connection/net_http.rb +2 -2
- data/lib/uber-s3/error.rb +89 -0
- data/lib/uber-s3/object.rb +21 -24
- data/lib/uber-s3/operation/object/content_md5.rb +1 -0
- data/lib/uber-s3/operation.rb +3 -31
- data/lib/uber-s3/response.rb +49 -0
- data/lib/uber-s3/version.rb +1 -1
- data/lib/uber-s3.rb +2 -1
- metadata +12 -11
- data/lib/uber-s3/exceptions.rb +0 -7
data/lib/uber-s3/bucket.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
class UberS3
|
2
2
|
class Bucket
|
3
|
-
|
4
3
|
attr_accessor :client, :name
|
5
4
|
|
6
5
|
def initialize(client, name)
|
@@ -24,11 +23,11 @@ class UberS3
|
|
24
23
|
def object(key)
|
25
24
|
Object.new(self, key)
|
26
25
|
end
|
26
|
+
alias_method :[], :object
|
27
27
|
|
28
28
|
def get(key)
|
29
29
|
object(key).fetch
|
30
30
|
end
|
31
|
-
alias_method :[], :get
|
32
31
|
|
33
32
|
def exists?(key)
|
34
33
|
object(key).exists?
|
@@ -40,6 +39,8 @@ class UberS3
|
|
40
39
|
|
41
40
|
|
42
41
|
class ObjectList
|
42
|
+
include Enumerable
|
43
|
+
|
43
44
|
attr_accessor :bucket, :key, :options, :objects
|
44
45
|
|
45
46
|
def initialize(bucket, key, options={})
|
@@ -52,14 +53,10 @@ class UberS3
|
|
52
53
|
def fetch(marker=nil)
|
53
54
|
@objects = []
|
54
55
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
raise UberS3Error, response.inspect
|
60
|
-
else
|
61
|
-
@objects = parse_contents(response[:body])
|
62
|
-
end
|
56
|
+
default_max_keys = 500
|
57
|
+
response = bucket.connection.get("/?prefix=#{CGI.escape(key)}&marker=#{marker}&max-keys=#{default_max_keys}")
|
58
|
+
|
59
|
+
@objects = parse_contents(response.body)
|
63
60
|
end
|
64
61
|
|
65
62
|
def parse_contents(xml)
|
@@ -5,9 +5,8 @@ module UberS3::Connection
|
|
5
5
|
class EmHttp < Adapter
|
6
6
|
|
7
7
|
# NOTE: this will be very difficult to support
|
8
|
-
# with our interface.. will need lots of work
|
9
|
-
#
|
10
|
-
# fibered mode
|
8
|
+
# with our interface.. will need lots of work.
|
9
|
+
# We may only want to support async with fibers.
|
11
10
|
|
12
11
|
end
|
13
12
|
end
|
@@ -14,12 +14,12 @@ module UberS3::Connection
|
|
14
14
|
|
15
15
|
r = EM::HttpRequest.new(url).send(verb, params)
|
16
16
|
|
17
|
-
{
|
17
|
+
UberS3::Response.new({
|
18
18
|
:status => r.response_header.status,
|
19
19
|
:header => r.response_header,
|
20
20
|
:body => r.response,
|
21
21
|
:raw => r
|
22
|
-
}
|
22
|
+
})
|
23
23
|
end
|
24
24
|
|
25
25
|
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
class UberS3
|
2
|
+
|
3
|
+
module Error
|
4
|
+
|
5
|
+
class Standard < StandardError
|
6
|
+
def initialize(key, message)
|
7
|
+
super("#{key}: #{message}")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Unknown < StandardError; end
|
12
|
+
|
13
|
+
class AccessDenied < Standard; end
|
14
|
+
class AccountProblem < Standard; end
|
15
|
+
class AmbiguousGrantByEmailAddress < Standard; end
|
16
|
+
class BadDigest < Standard; end
|
17
|
+
class BucketAlreadyExists < Standard; end
|
18
|
+
class BucketAlreadyOwnedByYou < Standard; end
|
19
|
+
class BucketNotEmpty < Standard; end
|
20
|
+
class CredentialsNotSupported < Standard; end
|
21
|
+
class CrossLocationLoggingProhibited < Standard; end
|
22
|
+
class EntityTooSmall < Standard; end
|
23
|
+
class EntityTooLarge < Standard; end
|
24
|
+
class ExpiredToken < Standard; end
|
25
|
+
class IllegalVersioningConfigurationException < Standard; end
|
26
|
+
class IncompleteBody < Standard; end
|
27
|
+
class IncorrectNumberOfFilesInPostRequest < Standard; end
|
28
|
+
class InlineDataTooLarge < Standard; end
|
29
|
+
class InternalError < Standard; end
|
30
|
+
class InvalidAccessKeyId < Standard; end
|
31
|
+
class InvalidAddressingHeader < Standard; end
|
32
|
+
class InvalidArgument < Standard; end
|
33
|
+
class InvalidBucketName < Standard; end
|
34
|
+
class InvalidDigest < Standard; end
|
35
|
+
class InvalidLocationConstraint < Standard; end
|
36
|
+
class InvalidPart < Standard; end
|
37
|
+
class InvalidPartOrder < Standard; end
|
38
|
+
class InvalidPayer < Standard; end
|
39
|
+
class InvalidPolicyDocument < Standard; end
|
40
|
+
class InvalidRange < Standard; end
|
41
|
+
class InvalidRequest < Standard; end
|
42
|
+
class InvalidSecurity < Standard; end
|
43
|
+
class InvalidSOAPRequest < Standard; end
|
44
|
+
class InvalidStorageClass < Standard; end
|
45
|
+
class InvalidTargetBucketForLogging < Standard; end
|
46
|
+
class InvalidToken < Standard; end
|
47
|
+
class InvalidURI < Standard; end
|
48
|
+
class KeyTooLong < Standard; end
|
49
|
+
class MalformedACLError < Standard; end
|
50
|
+
class MalformedPOSTRequest < Standard; end
|
51
|
+
class MalformedXML < Standard; end
|
52
|
+
class MaxMessageLengthExceeded < Standard; end
|
53
|
+
class MaxPostPreDataLengthExceededError < Standard; end
|
54
|
+
class MetadataTooLarge < Standard; end
|
55
|
+
class MethodNotAllowed < Standard; end
|
56
|
+
class MissingAttachment < Standard; end
|
57
|
+
class MissingContentLength < Standard; end
|
58
|
+
class MissingRequestBodyError < Standard; end
|
59
|
+
class MissingSecurityElement < Standard; end
|
60
|
+
class MissingSecurityHeader < Standard; end
|
61
|
+
class NoLoggingStatusForKey < Standard; end
|
62
|
+
class NoSuchBucket < Standard; end
|
63
|
+
class NoSuchKey < Standard; end
|
64
|
+
class NoSuchUpload < Standard; end
|
65
|
+
class NoSuchVersion < Standard; end
|
66
|
+
class NotImplemented < Standard; end
|
67
|
+
class NotSignedUp < Standard; end
|
68
|
+
class NotSuchBucketPolicy < Standard; end
|
69
|
+
class OperationAborted < Standard; end
|
70
|
+
class PermanentRedirect < Standard; end
|
71
|
+
class PreconditionFailed < Standard; end
|
72
|
+
class Redirect < Standard; end
|
73
|
+
class RequestIsNotMultiPartContent < Standard; end
|
74
|
+
class RequestTimeout < Standard; end
|
75
|
+
class RequestTimeTooSkewed < Standard; end
|
76
|
+
class RequestTorrentOfBucketError < Standard; end
|
77
|
+
class SignatureDoesNotMatch < Standard; end
|
78
|
+
class ServiceUnavailable < Standard; end
|
79
|
+
class SlowDown < Standard; end
|
80
|
+
class TemporaryRedirect < Standard; end
|
81
|
+
class TokenRefreshRequired < Standard; end
|
82
|
+
class TooManyBuckets < Standard; end
|
83
|
+
class UnexpectedContent < Standard; end
|
84
|
+
class UnresolvableGrantByEmailAddress < Standard; end
|
85
|
+
class UserKeyMustBeSpecified < Standard; end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
data/lib/uber-s3/object.rb
CHANGED
@@ -1,25 +1,23 @@
|
|
1
1
|
class UberS3
|
2
2
|
class Object
|
3
|
-
include Operation::Object::
|
3
|
+
include Operation::Object::AccessPolicy
|
4
|
+
include Operation::Object::CacheControl
|
5
|
+
include Operation::Object::ContentDisposition
|
6
|
+
include Operation::Object::ContentEncoding
|
7
|
+
include Operation::Object::ContentMd5
|
8
|
+
include Operation::Object::ContentType
|
9
|
+
include Operation::Object::Expires
|
10
|
+
include Operation::Object::Meta
|
11
|
+
include Operation::Object::StorageClass
|
4
12
|
|
5
|
-
attr_accessor :bucket, :key, :value, :size, :
|
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
|
13
|
+
attr_accessor :bucket, :key, :value, :size, :error
|
16
14
|
|
17
15
|
def initialize(bucket, key, value=nil, options={})
|
18
16
|
self.bucket = bucket
|
19
17
|
self.key = key
|
20
18
|
self.value = value
|
21
19
|
|
22
|
-
# Init state
|
20
|
+
# Init current state
|
23
21
|
infer_content_type!
|
24
22
|
|
25
23
|
# Call operation methods based on options passed
|
@@ -31,11 +29,11 @@ class UberS3
|
|
31
29
|
end
|
32
30
|
|
33
31
|
def exists?
|
34
|
-
bucket.connection.head(key)
|
32
|
+
bucket.connection.head(key).status == 200
|
35
33
|
end
|
36
34
|
|
37
35
|
def fetch
|
38
|
-
self.value = bucket.connection.get(key)
|
36
|
+
self.value = bucket.connection.get(key).body
|
39
37
|
self
|
40
38
|
end
|
41
39
|
|
@@ -57,7 +55,9 @@ class UberS3
|
|
57
55
|
|
58
56
|
# Content MD5 integrity check
|
59
57
|
if !content_md5.nil?
|
60
|
-
|
58
|
+
self.content_md5 = Digest::MD5.hexdigest(value) if content_md5 == true
|
59
|
+
|
60
|
+
# We expect a md5 hex digest here
|
61
61
|
md5_digest = content_md5.unpack('a2'*16).collect {|i| i.hex.chr }.join
|
62
62
|
headers['Content-MD5'] = Base64.encode64(md5_digest).strip
|
63
63
|
end
|
@@ -75,18 +75,15 @@ class UberS3
|
|
75
75
|
# Let's do it
|
76
76
|
response = bucket.connection.put(key, headers, value)
|
77
77
|
|
78
|
-
|
79
|
-
|
80
|
-
self.errors = response[:body]
|
81
|
-
else
|
82
|
-
self.errors = nil
|
83
|
-
end
|
78
|
+
# Update error state
|
79
|
+
self.error = response.error
|
84
80
|
|
85
|
-
|
81
|
+
# Test for success....
|
82
|
+
response.status == 200
|
86
83
|
end
|
87
84
|
|
88
85
|
def delete
|
89
|
-
bucket.connection.delete(key)
|
86
|
+
bucket.connection.delete(key).status == 204
|
90
87
|
end
|
91
88
|
|
92
89
|
def value
|
data/lib/uber-s3/operation.rb
CHANGED
@@ -1,35 +1,7 @@
|
|
1
1
|
class UberS3
|
2
2
|
module Operation
|
3
|
-
|
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
|
-
|
26
|
-
require op
|
27
|
-
op_klass = instance_eval(group_module_name+'::'+op_klass_name)
|
28
|
-
|
29
|
-
base.send :include, op_klass
|
30
|
-
end
|
31
|
-
end
|
32
|
-
module_function :include_modules
|
33
|
-
|
34
3
|
end
|
35
4
|
end
|
5
|
+
|
6
|
+
# Load object operation modules
|
7
|
+
Dir[File.dirname(__FILE__) + '/operation/object/*.rb'].each {|f| require f }
|
@@ -0,0 +1,49 @@
|
|
1
|
+
class UberS3
|
2
|
+
class Response
|
3
|
+
|
4
|
+
attr_accessor :status, :header, :body, :raw, :error_key, :error_message
|
5
|
+
|
6
|
+
def initialize(options={})
|
7
|
+
if !([:status, :header, :body, :raw] - options.keys).empty?
|
8
|
+
raise "Expecting keys :status, :header, :body and :raw"
|
9
|
+
end
|
10
|
+
|
11
|
+
self.status = options[:status]
|
12
|
+
self.header = options[:header]
|
13
|
+
self.body = options[:body]
|
14
|
+
self.raw = options[:raw]
|
15
|
+
|
16
|
+
check_for_errors!
|
17
|
+
end
|
18
|
+
|
19
|
+
# TODO: can/should we normalize the keys..? downcase.. etc.?
|
20
|
+
# def header=(header)
|
21
|
+
# end
|
22
|
+
|
23
|
+
def check_for_errors!
|
24
|
+
return if status < 400 || body.to_s.empty?
|
25
|
+
|
26
|
+
# Errors are XML
|
27
|
+
doc = Util::XmlDocument.new(body)
|
28
|
+
|
29
|
+
self.error_key = doc.xpath('//Error/Code').first.text
|
30
|
+
self.error_message = doc.xpath('//Error/Message').first.text
|
31
|
+
|
32
|
+
error_klass = instance_eval("Error::#{error_key}") rescue nil
|
33
|
+
|
34
|
+
if error_klass.nil?
|
35
|
+
raise Error::Unknown, "HTTP Response: #{status}, Body: #{body}"
|
36
|
+
else
|
37
|
+
raise error_klass.new(error_key, error_message)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def error
|
42
|
+
if !error_key.nil?
|
43
|
+
"#{error_key}: #{error_message}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
data/lib/uber-s3/version.rb
CHANGED
data/lib/uber-s3.rb
CHANGED
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.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-10-
|
12
|
+
date: 2011-10-21 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mime-types
|
16
|
-
requirement: &
|
16
|
+
requirement: &70197560327260 !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: *70197560327260
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rake
|
27
|
-
requirement: &
|
27
|
+
requirement: &70197560326480 !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: *70197560326480
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rspec
|
38
|
-
requirement: &
|
38
|
+
requirement: &70197560325160 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,8 +43,8 @@ dependencies:
|
|
43
43
|
version: 2.7.0
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
47
|
-
description: A simple & very fast S3 client supporting sync
|
46
|
+
version_requirements: *70197560325160
|
47
|
+
description: A simple & very fast S3 client supporting sync / async HTTP adapters
|
48
48
|
email:
|
49
49
|
- peter@nulayer.com
|
50
50
|
executables: []
|
@@ -58,7 +58,7 @@ files:
|
|
58
58
|
- lib/uber-s3/connection/em_http_fibered.rb
|
59
59
|
- lib/uber-s3/connection/net_http.rb
|
60
60
|
- lib/uber-s3/connection.rb
|
61
|
-
- lib/uber-s3/
|
61
|
+
- lib/uber-s3/error.rb
|
62
62
|
- lib/uber-s3/object.rb
|
63
63
|
- lib/uber-s3/operation/object/access_policy.rb
|
64
64
|
- lib/uber-s3/operation/object/cache_control.rb
|
@@ -70,6 +70,7 @@ files:
|
|
70
70
|
- lib/uber-s3/operation/object/meta.rb
|
71
71
|
- lib/uber-s3/operation/object/storage_class.rb
|
72
72
|
- lib/uber-s3/operation.rb
|
73
|
+
- lib/uber-s3/response.rb
|
73
74
|
- lib/uber-s3/util/xml_document.rb
|
74
75
|
- lib/uber-s3/version.rb
|
75
76
|
- lib/uber-s3.rb
|
@@ -96,6 +97,6 @@ rubyforge_project:
|
|
96
97
|
rubygems_version: 1.8.11
|
97
98
|
signing_key:
|
98
99
|
specification_version: 3
|
99
|
-
summary: A simple & very fast S3 client supporting sync
|
100
|
+
summary: A simple & very fast S3 client supporting sync / async HTTP adapters
|
100
101
|
test_files: []
|
101
102
|
has_rdoc:
|