uber-s3 0.1.9 → 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/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Uber-S3
2
2
 
3
- A simple, but very fast, S3 client written in Ruby supporting
4
- synchronous and asynchronous HTTP communication.
3
+ A simple, but very fast, S3 client for Ruby supporting
4
+ synchronous (net-http) and asynchronous (em+fibers) io.
5
5
 
6
6
 
7
7
  ## Examples
@@ -16,7 +16,6 @@ s3 = UberS3.new({
16
16
  :access_key => 'abc',
17
17
  :secret_access_key => 'def',
18
18
  :bucket => 'funbucket',
19
- :persistent => true,
20
19
  :adapter => :em_http_fibered
21
20
  })
22
21
 
@@ -103,13 +102,13 @@ s3.objects('/path').each {|obj| puts obj }
103
102
 
104
103
  ## Ruby version notes
105
104
 
106
- * Tested on MRI 1.9.2 (net_http / em_http_fibered adapters) -- recommended
107
- * Ruby 1.8.7 works for net/http clients, em_http_fibered adapter requires fibers (duh)
108
- * JRuby in 1.9 mode + em_http_fibered adapter should work, but held back because of issues with EM
105
+ * Tested on MRI 1.9.2, MRI 1.9.3 (net_http / em_http_fibered adapters)
106
+ * Tested on JRuby 1.7-dev in 1.9 mode (net_http)
107
+ * Ruby 1.8.7 works for net/http clients, em_http_fibered adapter requires fibers
109
108
 
110
109
  ## Other notes
111
110
 
112
- * If Nokogiri is available, it will use it instead of REXML
111
+ * If Nokogiri is available, it will be automatically used instead of REXML
113
112
 
114
113
  ## TODO
115
114
 
@@ -151,4 +150,4 @@ Yea... async adapter dominates. The 100x1KB files were 29x faster to upload, and
151
150
 
152
151
  ## License
153
152
 
154
- MIT License - Copyright (c) 2011 Nulayer Inc.
153
+ MIT License - Copyright (c) 2012 Nulayer Inc.
data/lib/uber-s3.rb CHANGED
@@ -12,7 +12,7 @@ class UberS3
12
12
  extend Forwardable
13
13
 
14
14
  attr_accessor :connection, :bucket
15
- def_delegators :@bucket, :store, :set, :object, :get, :[], :exists?, :objects
15
+ def_delegators :@bucket, :store, :set, :object, :get, :head, :[], :exists?, :objects
16
16
 
17
17
  def initialize(options={})
18
18
  self.connection = Connection.open(self, options)
@@ -24,7 +24,7 @@ class UberS3
24
24
  end
25
25
 
26
26
  def bucket=(bucket)
27
- @bucket = bucket.is_a?(Bucket) ? bucket : Bucket.new(self, bucket)
27
+ @bucket = bucket.is_a?(String) ? Bucket.new(self, bucket) : bucket
28
28
  end
29
29
  end
30
30
 
@@ -1,10 +1,10 @@
1
1
  class UberS3
2
2
  class Bucket
3
- attr_accessor :client, :name
3
+ attr_accessor :s3, :name
4
4
 
5
- def initialize(client, name)
6
- self.client = client
7
- self.name = name
5
+ def initialize(s3, name)
6
+ self.s3 = s3
7
+ self.name = name
8
8
  end
9
9
 
10
10
  def to_s
@@ -12,7 +12,7 @@ class UberS3
12
12
  end
13
13
 
14
14
  def connection
15
- client.connection
15
+ s3.connection
16
16
  end
17
17
 
18
18
  def store(key, value, options={})
@@ -29,6 +29,10 @@ class UberS3
29
29
  object(key).fetch
30
30
  end
31
31
 
32
+ def head(key)
33
+ object(key).head
34
+ end
35
+
32
36
  def exists?(key)
33
37
  object(key).exists?
34
38
  end
@@ -1,7 +1,7 @@
1
1
  class UberS3
2
2
  module Connection
3
3
 
4
- def self.open(client, options={})
4
+ def self.open(s3, options={})
5
5
  adapter = options.delete(:adapter) || :net_http
6
6
 
7
7
  begin
@@ -11,19 +11,20 @@ class UberS3
11
11
  raise "Cannot load #{adapter} adapter class"
12
12
  end
13
13
 
14
- klass.new(client, options)
14
+ klass.new(s3, options)
15
15
  end
16
16
 
17
17
 
18
18
  class Adapter
19
19
 
20
- attr_accessor :client, :access_key, :secret_access_key, :persistent, :defaults
20
+ attr_accessor :s3, :http, :uri, :access_key, :secret_access_key, :defaults
21
21
 
22
- def initialize(client, options={})
23
- self.client = client
22
+ def initialize(s3, options={})
23
+ self.s3 = s3
24
+ self.http = nil
25
+ self.uri = nil
24
26
  self.access_key = options[:access_key]
25
27
  self.secret_access_key = options[:secret_access_key]
26
- self.persistent = (options[:persistent].nil? ? true : options[:persistent])
27
28
  self.defaults = options[:defaults] || {}
28
29
  end
29
30
 
@@ -36,22 +37,31 @@ class UberS3
36
37
  # Default headers
37
38
  headers['Date'] = Time.now.httpdate if !headers.keys.include?('Date')
38
39
  headers['User-Agent'] ||= "UberS3 v#{UberS3::VERSION}"
39
- headers['Connection'] = (persistent ? 'keep-alive' : 'close')
40
+ headers['Connection'] ||= 'keep-alive'
40
41
 
41
42
  if body
42
43
  headers['Content-Length'] ||= body.bytesize.to_s
43
44
  end
44
45
 
45
46
  # Authorize the request
46
- signature = Authorization.sign(client, verb, path, headers)
47
+ signature = Authorization.sign(s3, verb, path, headers)
47
48
  headers['Authorization'] = "AWS #{access_key}:#{signature}"
48
49
 
49
50
  # Make the request
50
- url = "http://#{client.bucket}.s3.amazonaws.com/#{path}"
51
+ url = "http://#{s3.bucket}.s3.amazonaws.com/#{path}"
51
52
  request(verb, url, headers, body)
52
53
  end
53
54
  end
54
55
 
56
+ def uri=(uri)
57
+ # Reset the http connection if the host/port change
58
+ if !@uri.nil? && !(uri.host == @uri.host && uri.port == @uri.port)
59
+ self.http = nil
60
+ end
61
+
62
+ @uri = uri
63
+ end
64
+
55
65
  def request(verb, url, headers={}, body=nil)
56
66
  raise "Abstract method"
57
67
  end
@@ -1,5 +1,4 @@
1
1
  require 'net/http'
2
- require 'net/http/persistent'
3
2
 
4
3
  module UberS3::Connection
5
4
  class NetHttp < Adapter
@@ -10,27 +9,31 @@ module UberS3::Connection
10
9
  headers['Accept-Encoding'] = 'gzip, deflate'
11
10
  end
12
11
 
13
- uri = URI.parse(url)
12
+ self.uri = URI.parse(url)
14
13
 
15
- if persistent
16
- http = Net::HTTP::Persistent.new("#{access_key}:#{client.bucket}")
17
- else
18
- http = Net::HTTP.new(uri.host, uri.port)
14
+ # Init and open a HTTP connection
15
+ self.http ||= Net::HTTP.new(uri.host, uri.port)
16
+ if !http.started? || !http.active?
17
+ http.start
18
+
19
+ if Socket.const_defined?(:TCP_NODELAY)
20
+ socket = http.instance_variable_get(:@socket)
21
+ socket.io.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, true)
22
+ end
19
23
  end
20
-
24
+
21
25
  req_klass = instance_eval("Net::HTTP::"+verb.to_s.capitalize)
22
26
  req = req_klass.new(uri.to_s, headers)
23
27
 
24
28
  req.body = body if !body.nil? && !body.empty?
25
-
26
- if persistent
27
- r = http.request(uri, req)
28
- else
29
- r = http.request(req)
30
- end
31
-
29
+
30
+ # Make HTTP request
31
+ r = http.request(req)
32
+
33
+ # $stderr.puts "active? " + http.active?.to_s
34
+
32
35
  # Auto-decode any gzipped objects
33
- if verb == :get && r.header['content-encoding'] == 'gzip'
36
+ if verb == :get && r.header['Content-Encoding'] == 'gzip'
34
37
  gz = Zlib::GzipReader.new(StringIO.new(r.body))
35
38
  response_body = gz.read
36
39
  else
@@ -131,9 +131,10 @@ class UberS3
131
131
  def parse_response_header!
132
132
  # Meta..
133
133
  self.meta ||= {}
134
- response.header.keys.sort.select {|k| k =~ /^x-amz-meta-/ }.each do |amz_key|
134
+ response.header.keys.sort.select {|k| k =~ /^x.amz.meta./i }.each do |amz_key|
135
+
135
136
  # TODO.. value is an array.. meaning a meta attribute can have multiple values
136
- meta[amz_key.gsub(/^x-amz-meta-/, '')] = response.header[amz_key].first
137
+ meta[amz_key.gsub(/^x.amz.meta./i, '')] = [response.header[amz_key]].flatten.first
137
138
 
138
139
  # TODO.. em-http adapters return headers that look like X_AMZ_META_ .. very annoying.
139
140
  end
@@ -1,3 +1,3 @@
1
1
  class UberS3
2
- VERSION = '0.1.9'
2
+ VERSION = '0.2.1'
3
3
  end
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.9
4
+ version: 0.2.1
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: 2012-03-21 00:00:00.000000000 Z
12
+ date: 2012-04-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mime-types
16
- requirement: &70281335651220 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,21 +21,15 @@ dependencies:
21
21
  version: '1.17'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70281335651220
25
- - !ruby/object:Gem::Dependency
26
- name: net-http-persistent
27
- requirement: &70281335650160 !ruby/object:Gem::Requirement
24
+ version_requirements: !ruby/object:Gem::Requirement
28
25
  none: false
29
26
  requirements:
30
27
  - - ~>
31
28
  - !ruby/object:Gem::Version
32
- version: '2.5'
33
- type: :runtime
34
- prerelease: false
35
- version_requirements: *70281335650160
29
+ version: '1.17'
36
30
  - !ruby/object:Gem::Dependency
37
31
  name: rake
38
- requirement: &70281335649600 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
39
33
  none: false
40
34
  requirements:
41
35
  - - ! '>='
@@ -43,10 +37,15 @@ dependencies:
43
37
  version: '0'
44
38
  type: :development
45
39
  prerelease: false
46
- version_requirements: *70281335649600
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
47
46
  - !ruby/object:Gem::Dependency
48
47
  name: rspec
49
- requirement: &70281335648100 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
50
49
  none: false
51
50
  requirements:
52
51
  - - ~>
@@ -54,7 +53,12 @@ dependencies:
54
53
  version: 2.7.0
55
54
  type: :development
56
55
  prerelease: false
57
- version_requirements: *70281335648100
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 2.7.0
58
62
  description: A simple & very fast S3 client supporting sync / async HTTP adapters
59
63
  email:
60
64
  - peter@nulayer.com
@@ -104,8 +108,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
104
108
  version: 1.3.6
105
109
  requirements: []
106
110
  rubyforge_project:
107
- rubygems_version: 1.8.17
111
+ rubygems_version: 1.8.23
108
112
  signing_key:
109
113
  specification_version: 3
110
114
  summary: A simple & very fast S3 client supporting sync / async HTTP adapters
111
115
  test_files: []
116
+ has_rdoc: