s3 0.3.4 → 0.3.5

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/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- s3 (0.3.3)
4
+ s3 (0.3.5)
5
5
  proxies
6
6
 
7
7
  GEM
data/Rakefile CHANGED
@@ -1,5 +1,6 @@
1
1
  require "bundler"
2
2
  Bundler::GemHelper.install_tasks
3
+ Bundler.setup
3
4
 
4
5
  require "rake/testtask"
5
6
  require "rake/rdoctask"
data/lib/s3.rb CHANGED
@@ -15,6 +15,7 @@ require "s3/parser"
15
15
  require "s3/bucket"
16
16
  require "s3/connection"
17
17
  require "s3/exceptions"
18
+ require "s3/request"
18
19
  require "s3/object"
19
20
  require "s3/service"
20
21
  require "s3/signature"
data/lib/s3/connection.rb CHANGED
@@ -19,7 +19,10 @@ module S3
19
19
  # * <tt>:timeout</tt> - Timeout to use by the Net::HTTP object
20
20
  # (60 by default)
21
21
  # * <tt>:proxy</tt> - Hash for Net::HTTP Proxy settings
22
- # { :host => "proxy.mydomain.com", :port => "80, :user => "user_a", :password => "secret" }
22
+ # { :host => "proxy.mydomain.com", :port => "80, :user => "user_a", :password => "secret" }
23
+ # * <tt>:proxy</tt> - Hash for Net::HTTP Proxy settings
24
+ # * <tt>:chunk_size</tt> - Size of a chunk when streaming
25
+ # (1048576 (1 MiB) by default)
23
26
  def initialize(options = {})
24
27
  @access_key_id = options.fetch(:access_key_id)
25
28
  @secret_access_key = options.fetch(:secret_access_key)
@@ -27,6 +30,7 @@ module S3
27
30
  @debug = options.fetch(:debug, false)
28
31
  @timeout = options.fetch(:timeout, 60)
29
32
  @proxy = options.fetch(:proxy, nil)
33
+ @chunk_size = options.fetch(:chunk_size, 1048576)
30
34
  end
31
35
 
32
36
  # Makes request with given HTTP method, sets missing parameters,
@@ -53,7 +57,7 @@ module S3
53
57
  def request(method, options)
54
58
  host = options.fetch(:host, HOST)
55
59
  path = options.fetch(:path)
56
- body = options.fetch(:body, "")
60
+ body = options.fetch(:body, nil)
57
61
  params = options.fetch(:params, {})
58
62
  headers = options.fetch(:headers, {})
59
63
 
@@ -63,14 +67,21 @@ module S3
63
67
  end
64
68
 
65
69
  path = URI.escape(path)
66
- request = request_class(method).new(path)
70
+ request = Request.new(@chunk_size, method.to_s.upcase, !!body, true, path)
67
71
 
68
72
  headers = self.class.parse_headers(headers)
69
73
  headers.each do |key, value|
70
74
  request[key] = value
71
75
  end
72
76
 
73
- request.body = body
77
+ if body
78
+ if body.respond_to?(:read)
79
+ request.body_stream = body
80
+ else
81
+ request.body = body
82
+ end
83
+ request.content_length = body.respond_to?(:lstat) ? body.stat.size : body.size
84
+ end
74
85
 
75
86
  send_request(host, request)
76
87
  end
@@ -114,7 +125,7 @@ module S3
114
125
  # Hash of headers translated from symbol to string, containing
115
126
  # only interesting headers
116
127
  def self.parse_headers(headers)
117
- interesting_keys = [:content_type, :x_amz_acl, :x_amz_storage_class, :range,
128
+ interesting_keys = [:content_type, :cache_control, :x_amz_acl, :x_amz_storage_class, :range,
118
129
  :if_modified_since, :if_unmodified_since,
119
130
  :if_match, :if_none_match,
120
131
  :content_disposition, :content_encoding,
@@ -143,19 +154,6 @@ module S3
143
154
 
144
155
  private
145
156
 
146
- def request_class(method)
147
- case method
148
- when :get
149
- request_class = Net::HTTP::Get
150
- when :head
151
- request_class = Net::HTTP::Head
152
- when :put
153
- request_class = Net::HTTP::Put
154
- when :delete
155
- request_class = Net::HTTP::Delete
156
- end
157
- end
158
-
159
157
  def port
160
158
  use_ssl ? 443 : 80
161
159
  end
@@ -177,7 +175,7 @@ module S3
177
175
  response = http(host).start do |http|
178
176
  host = http.address
179
177
 
180
- request['Date'] ||= Time.now.httpdate
178
+ request["Date"] ||= Time.now.httpdate
181
179
 
182
180
  if request.body
183
181
  request["Content-Type"] ||= "application/octet-stream"
@@ -197,7 +195,7 @@ module S3
197
195
  if response.code.to_i == 307
198
196
  if response.body
199
197
  doc = Document.new response.body
200
- send_request(doc.elements['Error'].elements['Endpoint'].text, request, true)
198
+ send_request(doc.elements["Error"].elements["Endpoint"].text, request, true)
201
199
  end
202
200
  else
203
201
  handle_response(response)
data/lib/s3/object.rb CHANGED
@@ -5,7 +5,7 @@ module S3
5
5
  include Parser
6
6
  extend Forwardable
7
7
 
8
- attr_accessor :content_type, :content_disposition, :content_encoding
8
+ attr_accessor :content_type, :content_disposition, :content_encoding, :cache_control
9
9
  attr_reader :last_modified, :etag, :size, :bucket, :key, :acl, :storage_class
10
10
  attr_writer :content
11
11
 
@@ -40,8 +40,8 @@ module S3
40
40
  def acl=(acl)
41
41
  @acl = acl.to_s.gsub("_", "-") if acl
42
42
  end
43
-
44
- # Assigns a new storage class (RRS) to the object. Please note
43
+
44
+ # Assigns a new storage class (RRS) to the object. Please note
45
45
  # that the storage class is not retrieved from the server and set
46
46
  # to "STANDARD" by default.
47
47
  #
@@ -150,6 +150,7 @@ module S3
150
150
  headers[:content_type] = options[:content_type] || content_type || "application/octet-stream"
151
151
  headers[:content_encoding] = options[:content_encoding] if options[:content_encoding]
152
152
  headers[:content_disposition] = options[:content_disposition] if options[:content_disposition]
153
+ headers[:cache_control] = options[:cache_control] if options[:cache_control]
153
154
  headers[:x_amz_copy_source] = full_key
154
155
  headers[:x_amz_metadata_directive] = "REPLACE"
155
156
  headers[:x_amz_copy_source_if_match] = options[:if_match] if options[:if_match]
@@ -165,6 +166,7 @@ module S3
165
166
  object.content_type = response["content-type"]
166
167
  object.content_encoding = response["content-encoding"]
167
168
  object.content_disposition = response["content-disposition"]
169
+ object.cache_control = response["cache-control"]
168
170
  object
169
171
  end
170
172
 
@@ -185,8 +187,7 @@ module S3
185
187
  end
186
188
 
187
189
  def put_object
188
- body = content.is_a?(IO) ? content.read : content
189
- response = object_request(:put, :body => body, :headers => dump_headers)
190
+ response = object_request(:put, :body => content, :headers => dump_headers)
190
191
  parse_headers(response)
191
192
  end
192
193
 
@@ -200,6 +201,7 @@ module S3
200
201
  self.last_modified = options[:last_modified]
201
202
  self.etag = options[:etag]
202
203
  self.size = options[:size]
204
+ self.cache_control = options[:cache_control]
203
205
  end
204
206
 
205
207
  def object_request(method, options = {})
@@ -229,6 +231,7 @@ module S3
229
231
  headers[:content_type] = @content_type || "application/octet-stream"
230
232
  headers[:content_encoding] = @content_encoding if @content_encoding
231
233
  headers[:content_disposition] = @content_disposition if @content_disposition
234
+ headers[:cache_control] = @cache_control if @cache_control
232
235
  headers
233
236
  end
234
237
 
@@ -236,6 +239,7 @@ module S3
236
239
  self.etag = response["etag"]
237
240
  self.content_type = response["content-type"]
238
241
  self.content_disposition = response["content-disposition"]
242
+ self.cache_control = response["cache-control"]
239
243
  self.content_encoding = response["content-encoding"]
240
244
  self.last_modified = response["last-modified"]
241
245
  if response["content-range"]
data/lib/s3/request.rb ADDED
@@ -0,0 +1,31 @@
1
+ module S3
2
+ # Class responsible for sending chunked requests
3
+ # properly. Net::HTTPGenericRequest has hardcoded chunk_size, so we
4
+ # inherit the class and override chunk_size.
5
+ class Request < Net::HTTPGenericRequest
6
+ def initialize(chunk_size, m, reqbody, resbody, path, initheader = nil)
7
+ @chunk_size = chunk_size
8
+ super(m, reqbody, resbody, path, initheader)
9
+ end
10
+
11
+ private
12
+
13
+ def send_request_with_body_stream(sock, ver, path, f)
14
+ unless content_length() or chunked?
15
+ raise ArgumentError, "Content-Length not given and Transfer-Encoding is not `chunked'"
16
+ end
17
+ supply_default_content_type
18
+ write_header sock, ver, path
19
+ if chunked?
20
+ while s = f.read(@chunk_size)
21
+ sock.write(sprintf("%x\r\n", s.length) << s << "\r\n")
22
+ end
23
+ sock.write "0\r\n\r\n"
24
+ else
25
+ while s = f.read(@chunk_size)
26
+ sock.write s
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
data/lib/s3/service.rb CHANGED
@@ -22,12 +22,15 @@ module S3
22
22
  # (false by default)
23
23
  # * <tt>:timeout</tt> - Timeout to use by the Net::HTTP object
24
24
  # (60 by default)
25
+ # * <tt>:chunk_size</tt> - Size of a chunk when streaming
26
+ # (1048576 (1 MiB) by default)
25
27
  def initialize(options)
26
28
  @access_key_id = options.fetch(:access_key_id)
27
29
  @secret_access_key = options.fetch(:secret_access_key)
28
30
  @use_ssl = options.fetch(:use_ssl, false)
29
31
  @timeout = options.fetch(:timeout, 60)
30
32
  @debug = options.fetch(:debug, false)
33
+ @chunk_size = options.fetch(:chunk_size, 1048576)
31
34
 
32
35
  raise ArgumentError, "Missing proxy settings. Must specify at least :host." if options[:proxy] && !options[:proxy][:host]
33
36
  @proxy = options.fetch(:proxy, nil)
@@ -74,7 +77,8 @@ module S3
74
77
  :use_ssl => @use_ssl,
75
78
  :timeout => @timeout,
76
79
  :debug => @debug,
77
- :proxy => @proxy)
80
+ :proxy => @proxy,
81
+ :chunk_size => @chunk_size)
78
82
  end
79
83
  @connection
80
84
  end
data/lib/s3/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module S3
2
- VERSION = "0.3.4"
2
+ VERSION = "0.3.5"
3
3
  end
data/test/object_test.rb CHANGED
@@ -11,6 +11,8 @@ class ObjectTest < Test::Unit::TestCase
11
11
  @object_lena = S3::Object.send(:new, @bucket_images, :key => "Lena.png")
12
12
  @object_lena.content = "test"
13
13
  @object_carmen = S3::Object.send(:new, @bucket_images, :key => "Carmen.png")
14
+ @object_mac = S3::Object.send(:new, @bucket_images, :key => "Mac.png", :cache_control => "max-age=315360000")
15
+ @object_mac.content = "test2"
14
16
 
15
17
  @response_binary = Net::HTTPOK.new("1.1", "200", "OK")
16
18
  @response_binary.stubs(:body).returns("test".respond_to?(:force_encoding) ? "test".force_encoding(Encoding::BINARY) : "test")
@@ -105,6 +107,12 @@ class ObjectTest < Test::Unit::TestCase
105
107
  assert @object_lena.save
106
108
  end
107
109
 
110
+ test "save with cache control headers" do
111
+ assert_equal "max-age=315360000", @object_mac.cache_control
112
+ @object_mac.expects(:object_request).with(:put, :body=>"test2", :headers=>{ :x_amz_acl=>"public-read", :x_amz_storage_class=>"STANDARD", :content_type=>"application/octet-stream", :cache_control=>"max-age=315360000" }).returns(@response_binary)
113
+ assert @object_mac.save
114
+ end
115
+
108
116
  test "content and parse headers" do
109
117
  @object_lena.expects(:object_request).with(:get, {}).returns(@response_binary)
110
118
 
data/test/test_helper.rb CHANGED
@@ -1,6 +1,3 @@
1
- require "rubygems"
2
- require "bundler/setup"
3
-
4
- Bundler.require
5
1
  require "test/unit"
6
2
  require "mocha"
3
+ require "s3"
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: s3
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 25
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
8
  - 3
8
- - 4
9
- version: 0.3.4
9
+ - 5
10
+ version: 0.3.5
10
11
  platform: ruby
11
12
  authors:
12
13
  - "Jakub Ku\xC5\xBAma"
@@ -14,63 +15,67 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-09-25 00:00:00 +02:00
18
+ date: 2010-10-05 00:00:00 +02:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
- name: proxies
22
- prerelease: false
23
22
  requirement: &id001 !ruby/object:Gem::Requirement
24
23
  none: false
25
24
  requirements:
26
25
  - - ">="
27
26
  - !ruby/object:Gem::Version
27
+ hash: 3
28
28
  segments:
29
29
  - 0
30
30
  version: "0"
31
31
  type: :runtime
32
+ name: proxies
33
+ prerelease: false
32
34
  version_requirements: *id001
33
35
  - !ruby/object:Gem::Dependency
34
- name: test-unit
35
- prerelease: false
36
36
  requirement: &id002 !ruby/object:Gem::Requirement
37
37
  none: false
38
38
  requirements:
39
39
  - - ">="
40
40
  - !ruby/object:Gem::Version
41
+ hash: 3
41
42
  segments:
42
43
  - 2
43
44
  - 0
44
45
  version: "2.0"
45
46
  type: :development
47
+ name: test-unit
48
+ prerelease: false
46
49
  version_requirements: *id002
47
50
  - !ruby/object:Gem::Dependency
48
- name: mocha
49
- prerelease: false
50
51
  requirement: &id003 !ruby/object:Gem::Requirement
51
52
  none: false
52
53
  requirements:
53
54
  - - ">="
54
55
  - !ruby/object:Gem::Version
56
+ hash: 3
55
57
  segments:
56
58
  - 0
57
59
  version: "0"
58
60
  type: :development
61
+ name: mocha
62
+ prerelease: false
59
63
  version_requirements: *id003
60
64
  - !ruby/object:Gem::Dependency
61
- name: bundler
62
- prerelease: false
63
65
  requirement: &id004 !ruby/object:Gem::Requirement
64
66
  none: false
65
67
  requirements:
66
68
  - - ">="
67
69
  - !ruby/object:Gem::Version
70
+ hash: 23
68
71
  segments:
69
72
  - 1
70
73
  - 0
71
74
  - 0
72
75
  version: 1.0.0
73
76
  type: :development
77
+ name: bundler
78
+ prerelease: false
74
79
  version_requirements: *id004
75
80
  description: "S3 library provides access to Amazon's Simple Storage Service. It supports both: European and US buckets through REST API."
76
81
  email:
@@ -98,6 +103,7 @@ files:
98
103
  - lib/s3/object.rb
99
104
  - lib/s3/objects_extension.rb
100
105
  - lib/s3/parser.rb
106
+ - lib/s3/request.rb
101
107
  - lib/s3/service.rb
102
108
  - lib/s3/signature.rb
103
109
  - lib/s3/version.rb
@@ -122,6 +128,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
122
128
  requirements:
123
129
  - - ">="
124
130
  - !ruby/object:Gem::Version
131
+ hash: 3
125
132
  segments:
126
133
  - 0
127
134
  version: "0"
@@ -130,6 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
130
137
  requirements:
131
138
  - - ">="
132
139
  - !ruby/object:Gem::Version
140
+ hash: 23
133
141
  segments:
134
142
  - 1
135
143
  - 3