raws 0.0.8 → 0.0.9

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.rdoc CHANGED
@@ -45,13 +45,11 @@ RAWS is a Ruby library for Amazon Web Service (AWS).
45
45
  p RAWS::SDB['test_domain'].get('2')
46
46
  p RAWS::SDB['test_domain'].get('3')
47
47
 
48
- RAWS::SDB['test_domain'].all.each do |a|
49
- key, data = a
48
+ RAWS::SDB['test_domain'].all.each do |key, data|
50
49
  p [key, data]
51
50
  end
52
51
 
53
- RAWS::SDB['test_domain'].all.filter('a = ?', 10).each do |a|
54
- key, data = a
52
+ RAWS::SDB['test_domain'].all.filter('a = ?', 10).each do |key, data|
55
53
  p [key, data]
56
54
  end
57
55
 
@@ -106,3 +104,13 @@ RAWS is a Ruby library for Amazon Web Service (AWS).
106
104
  Foo.delete_domain
107
105
 
108
106
  == S3 (Amazon Simple Storage Service)
107
+
108
+ require 'rubygems'
109
+ require 'raws'
110
+
111
+ RAWS.aws_access_key_id = _AWS_ACCESS_KEY_ID_
112
+ RAWS.aws_secret_access_key = _AWS_SECRET_ACCESS_KEY_
113
+
114
+ RAWS::S3.create_bucket('test_bucket')
115
+
116
+ RAWS::S3['test_bucket'].delete_bucket
data/Rakefile CHANGED
@@ -18,10 +18,12 @@ begin
18
18
  ) + Dir.glob("{bin,doc,lib}/**/*")
19
19
  s.require_path = "lib"
20
20
  s.has_rdoc = true
21
- s.add_dependency('pauldix-typhoeus', '>=0.1.2')
21
+ s.add_dependency('typhoeus', '>=0.1.9')
22
+ s.add_dependency('ht2p', '>=0.0.5')
22
23
  s.add_dependency('nokogiri', '>=1.3.3')
23
24
  s.add_dependency('uuidtools', '>=2.0.0')
24
25
  end
26
+ Jeweler::GemcutterTasks.new
25
27
  rescue LoadError
26
28
  puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
27
29
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.8
1
+ 0.0.9
@@ -0,0 +1,83 @@
1
+ require 'ht2p'
2
+
3
+ module RAWS::HTTP::HT2P
4
+ def self.connect(uri, &block)
5
+ response = nil
6
+ begin
7
+ HT2P::Client.new uri do |request|
8
+ response = block.call(Request.new(request))
9
+ end
10
+ rescue RAWS::HTTP::Redirect => e
11
+ r = e.response
12
+ uri = r.header['location'] || r.doc['Error']['Endpoint']
13
+ retry
14
+ end
15
+ response
16
+ end
17
+
18
+ class Request < RAWS::HTTP::Request
19
+ def initialize(request)
20
+ @request, @before_send = request, nil
21
+ end
22
+
23
+ def method
24
+ @request.method
25
+ end
26
+
27
+ def method=(val)
28
+ @request.method = val
29
+ end
30
+
31
+ def header
32
+ @request.header
33
+ end
34
+
35
+ def before_send(&block)
36
+ @before_send = block
37
+ end
38
+
39
+ def send(body=nil, &block)
40
+ RAWS.logger.debug self
41
+ @before_send && @before_send.call(self)
42
+ response = Response.new(@request.send(body, &block))
43
+ case response.code
44
+ when 200...300
45
+ response
46
+ when 300...400
47
+ response.parse
48
+ raise RAWS::HTTP::Redirect.new(response)
49
+ else
50
+ response.parse
51
+ raise RAWS::HTTP::Error.new(response)
52
+ end
53
+ end
54
+ end
55
+
56
+ class Response < RAWS::HTTP::Response
57
+ attr_reader :body, :doc
58
+
59
+ def initialize(response)
60
+ @response, @body, @doc = response, nil, nil
61
+ end
62
+
63
+ def code
64
+ @response.code
65
+ end
66
+
67
+ def header
68
+ @response.header
69
+ end
70
+
71
+ def receive(&block)
72
+ if block_given?
73
+ @response.receive(&block)
74
+ else
75
+ @body = @response.receive
76
+ end
77
+ end
78
+
79
+ def parse(params={})
80
+ @doc = RAWS.xml.parse(receive, params)
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,92 @@
1
+ require 'typhoeus'
2
+ require 'stringio'
3
+
4
+ class RAWS::HTTP::Typhoeus
5
+ def self.connect(uri, &block)
6
+ response = nil
7
+ begin
8
+ response = block.call(Request.new(uri))
9
+ rescue RAWS::HTTP::Redirect => e
10
+ r = e.response
11
+ uri = r.header['location'] || r.doc['Error']['Endpoint']
12
+ retry
13
+ end
14
+ response
15
+ end
16
+
17
+ class Request < RAWS::HTTP::Request
18
+ attr_reader :header
19
+ attr_accessor :uri, :method
20
+
21
+ def initialize(uri)
22
+ @uri, @header, @method, @before_send = uri, {}, :get , nil
23
+ end
24
+
25
+ def before_send(&block)
26
+ @before_send = block
27
+ end
28
+
29
+ def send(body=nil, &block)
30
+ RAWS.logger.debug self
31
+ @before_send && @before_send.call(self)
32
+ response = Response.new(
33
+ ::Typhoeus::Request.__send__(
34
+ @method.downcase.to_sym,
35
+ @uri,
36
+ :headers => @header,
37
+ :body => if block_given?
38
+ # TODO エラーにした方が。。。 
39
+ io = StringIO.new
40
+ block.call(io)
41
+ if io.size > 0
42
+ io.rewind
43
+ io.read
44
+ end
45
+ else
46
+ body
47
+ end
48
+ )
49
+ )
50
+ case response.code
51
+ when 200...300
52
+ response
53
+ when 300...400
54
+ response.parse
55
+ raise RAWS::HTTP::Redirect.new(response)
56
+ else
57
+ response.parse
58
+ raise RAWS::HTTP::Error.new(response)
59
+ end
60
+ end
61
+ end
62
+
63
+ class Response < RAWS::HTTP::Response
64
+ attr_reader :body, :doc
65
+
66
+ def initialize(response)
67
+ @response, @body, @doc = response, nil, nil
68
+ @header = @response.headers.split("\r\n").inject({}) do |ret, val|
69
+ if md = /(.+?):\s*(.*)/.match(val)
70
+ ret[md[1].downcase] = md[2]
71
+ end
72
+ ret
73
+ end
74
+ end
75
+
76
+ def code
77
+ @response.code
78
+ end
79
+
80
+ def receive(&block)
81
+ if block_given?
82
+ block.call(StringIO.new(@response.body)) # TODO エラーにした方が。。。
83
+ else
84
+ @body = @response.body
85
+ end
86
+ end
87
+
88
+ def parse(params={})
89
+ @doc = RAWS.xml.parse(receive, params)
90
+ end
91
+ end
92
+ end
data/lib/raws/http.rb ADDED
@@ -0,0 +1,25 @@
1
+ module RAWS
2
+ module HTTP
3
+ class Redirect < Exception
4
+ attr_reader :response
5
+
6
+ def initialize(response)
7
+ @response = response
8
+ end
9
+ end
10
+
11
+ class Error < StandardError
12
+ attr_reader :response
13
+
14
+ def initialize(response)
15
+ @response = response
16
+ end
17
+ end
18
+
19
+ class Request; end
20
+ class Response; end
21
+
22
+ autoload :Typhoeus, 'raws/http/typhoeus'
23
+ autoload :HT2P, 'raws/http/ht2p'
24
+ end
25
+ end
@@ -1,5 +1,3 @@
1
- require 'digest/md5'
2
-
3
1
  class RAWS::S3::Adapter
4
2
  module Adapter20060301
5
3
  URI_PARAMS = {
@@ -9,113 +7,227 @@ class RAWS::S3::Adapter
9
7
  :query => {}
10
8
  }
11
9
 
12
- def build_uri(params={})
13
- "#{params[:scheme]}://#{
14
- if params[:bucket]
15
- "#{params[:bucket]}.#{params[:host]}"
10
+ def parse_params(params)
11
+ params = URI_PARAMS.merge(params)
12
+
13
+ path = if bucket = params[:bucket]
14
+ if bucket.include?('.')
15
+ params.delete :bucket
16
+ params[:path] = "/#{bucket}#{params[:path]}"
16
17
  else
17
- params[:host]
18
+ "/#{bucket}#{params[:path]}"
18
19
  end
19
- }#{params[:path]}#{
20
- if params[:query].empty?
21
- ''
22
- else
23
- '?' << a[:query].map do |key, val|
24
- val ? "#{RAWS.escape(key)}=#{RAWS.escape(val)}" : RAWS.escape(key)
25
- end.sort.join(';')
20
+ else
21
+ params[:path]
22
+ end
23
+
24
+ unless params[:query].empty?
25
+ params[:path] += '?' << params[:query].map do |key, val|
26
+ val ? "#{RAWS.escape(key)}=#{RAWS.escape(val)}" : RAWS.escape(key)
27
+ end.sort.join(';')
28
+
29
+ params[:query].each do |key, val|
30
+ unless val
31
+ path << "?#{key}"
32
+ break
33
+ end
26
34
  end
27
- }"
35
+ end
36
+
37
+ [
38
+ "#{params[:scheme]}://#{
39
+ if params[:bucket]
40
+ "#{params[:bucket]}.#{params[:host]}"
41
+ else
42
+ params[:host]
43
+ end
44
+ }#{params[:path]}",
45
+ path
46
+ ]
28
47
  end
48
+ private :parse_params
29
49
 
30
- def sign(http_verb, content, type, date, path)
31
- "#{RAWS.aws_access_key_id}:#{
50
+ def sign(request, path)
51
+ request.header['authorization'] = "AWS #{RAWS.aws_access_key_id}:#{
32
52
  [
33
53
  ::OpenSSL::HMAC.digest(
34
54
  ::OpenSSL::Digest::SHA1.new,
35
55
  RAWS.aws_secret_access_key,
36
- [
37
- http_verb,
38
- content ? Digest::MD5.hexdigest(content) : '',
39
- type,
40
- date,
41
- path
42
- ].join("\n")
56
+ (
57
+ [
58
+ request.method,
59
+ request.header['content-md5'],
60
+ request.header['content-type'],
61
+ request.header['x-amz-date'] ? '' : request.header['date'],
62
+ ] + request.header.select do |key, val|
63
+ /^x-amz-/.match(key)
64
+ end.sort.map do |key, val|
65
+ "#{key}:#{val}"
66
+ end + [
67
+ path
68
+ ]
69
+ ).join("\n")
43
70
  )
44
71
  ].pack('m').strip
45
72
  }"
46
73
  end
74
+ private :sign
47
75
 
48
- def fetch(http_verb, _uri={}, options={}, content=nil, type='')
49
- date = Time.now.httpdate
50
- uri = URI_PARAMS.merge(_uri)
51
- r = RAWS.__send__(
52
- http_verb.downcase.to_sym,
53
- build_uri(uri),
54
- :headers => {
55
- 'Date' => date,
56
- 'Authorization' => "AWS #{
57
- sign(http_verb, content, type, date, uri[:path])
58
- }"
59
- }
60
- )
61
- data = RAWS.parse(Nokogiri::XML.parse(r.body), options)
62
- if 200 <= r.code && r.code <= 299
63
- data
64
- else
65
- raise RAWS::Error.new(r, data)
76
+ def connect(method, params={}, &block)
77
+ uri, path = parse_params params
78
+ RAWS::S3.http.connect(uri) do |request|
79
+ request.method = method
80
+ request.header['date'] = Time.now.httpdate
81
+ request.before_send do |_request|
82
+ sign _request, path
83
+ end
84
+ block.call request
66
85
  end
67
86
  end
68
87
 
69
88
  def get_service
70
- fetch('GET', {}, :multiple => 'Bucket')
89
+ connect 'GET' do |request|
90
+ response = request.send
91
+ response.parse :multiple => ['Bucket']
92
+ response
93
+ end
71
94
  end
72
95
 
73
- def put_bucket(bucket_name)
74
- fetch('PUT', :path => "/#{bucket_name}")
96
+ def put_bucket(bucket_name, location=nil, header={})
97
+ connect 'PUT', :bucket => bucket_name do |request|
98
+ request.header.merge! header
99
+ response = request.send(
100
+ if location
101
+ "<CreateBucketConfiguration>"
102
+ "<LocationConstraint>#{
103
+ location
104
+ }</LocationConstraint>"
105
+ "</CreateBucketConfiguration>"
106
+ end
107
+ )
108
+ response.receive
109
+ response
110
+ end
75
111
  end
76
112
 
77
- def put_request_payment(bucket_name)
78
- fetch(
79
- 'PUT',
80
- {
81
- :bucket => bucket_name,
82
- :query => {'requestPayment' => nil}
83
- }
84
- )
113
+ def put_request_payment(bucket_name, requester)
114
+ connect(
115
+ 'PUT',
116
+ :bucket => bucket_name,
117
+ :query => {'requestPayment' => nil}
118
+ ) do |request|
119
+ response = request.send\
120
+ '<RequestPaymentConfiguration'
121
+ ' xmlns="http://s3.amazonaws.com/doc/2006-03-01/">'
122
+ "<Payer>#{requester}</Payer>"
123
+ '</RequestPaymentConfiguration>'
124
+ response.receive
125
+ response
126
+ end
85
127
  end
86
128
 
87
129
  def get_bucket(bucket_name, params={})
88
- fetch(
89
- 'GET',
90
- {
91
- :bucket => bucket_name,
92
- :query => params
93
- }
94
- )
130
+ connect(
131
+ 'GET',
132
+ :bucket => bucket_name,
133
+ :query => params
134
+ ) do |request|
135
+ response = request.send
136
+ response.parse :multiple => ['Contents']
137
+ response
138
+ end
95
139
  end
96
140
 
97
141
  def get_request_payment(bucket_name)
98
- fetch(
99
- 'GET',
100
- {
101
- :bucket => bucket_name,
102
- :query => {'requestPayment' => nil}
103
- }
104
- )
142
+ connect(
143
+ 'GET',
144
+ :bucket => bucket_name,
145
+ :query => {'requestPayment' => nil}
146
+ ) do |request|
147
+ response = request.send
148
+ response.parse
149
+ response
150
+ end
105
151
  end
106
152
 
107
153
  def get_bucket_location(bucket_name)
108
- fetch(
109
- 'GET',
110
- {
111
- :bucket => bucket_name,
112
- :query => {'location' => nil}
113
- }
114
- )
154
+ connect(
155
+ 'GET',
156
+ :bucket => bucket_name,
157
+ :query => {'location' => nil}
158
+ ) do |request|
159
+ response = request.send
160
+ response.parse
161
+ response
162
+ end
115
163
  end
116
164
 
117
165
  def delete_bucket(bucket_name)
118
- fetch('DELETE', :path => "/#{bucket_name}")
166
+ connect 'DELETE', :bucket => bucket_name do |request|
167
+ request.send
168
+ end
169
+ end
170
+
171
+ def put_object(bucket_name, name, header, &block)
172
+ connect(
173
+ 'PUT',
174
+ :bucket => bucket_name,
175
+ :path => '/' << name
176
+ ) do |request|
177
+ request.header.merge!(header)
178
+ response = request.send(&block)
179
+ response.receive
180
+ response
181
+ end
182
+ end
183
+
184
+ def copy_object(src_bucket, src_name, dest_bucket, dest_name, header={})
185
+ connect(
186
+ 'PUT',
187
+ :bucket => dest_bucket,
188
+ :path => '/' << dest_name
189
+ ) do |request|
190
+ request.header.merge! header
191
+ request.header['x-amz-copy-source'] = "/#{src_bucket}/#{src_name}"
192
+ request.send
193
+ end
194
+ end
195
+
196
+ def get_object(bucket_name, name=nil, header={}, &block)
197
+ connect(
198
+ 'GET',
199
+ :bucket => bucket_name,
200
+ :path => "/#{name}"
201
+ ) do |request|
202
+ request.header.merge! header
203
+ response = request.send
204
+ response.receive(&block)
205
+ response
206
+ end
207
+ end
208
+
209
+ def head_object(bucket_name, name)
210
+ connect(
211
+ 'HEAD',
212
+ :bucket => bucket_name,
213
+ :path => '/' << name
214
+ ) do |request|
215
+ response = request.send
216
+ response.receive
217
+ response
218
+ end
219
+ end
220
+
221
+ def delete_object(bucket_name, name)
222
+ connect(
223
+ 'DELETE',
224
+ :bucket => bucket_name,
225
+ :path => '/' << name
226
+ ) do |request|
227
+ response = request.send
228
+ response.receive
229
+ response
230
+ end
119
231
  end
120
232
  end
121
233
 
@@ -0,0 +1,71 @@
1
+ module RAWS::S3::Model
2
+ module ClassMethods
3
+ attr_accessor :bucket_name
4
+
5
+ def create_bucket
6
+ RAWS::S3.create_bucket(self.bucket_name)
7
+ end
8
+
9
+ def delete_bucket(force=nil)
10
+ RAWS::S3.delete_bucket(self.bucket_name, force)
11
+ end
12
+ end
13
+
14
+ module InstanceMethods
15
+ def after_initialize; end
16
+ def before_delete; end
17
+ def after_delete; end
18
+ def before_save; end
19
+ def after_save; end
20
+ def before_update; end
21
+ def after_update; end
22
+ def before_insert; end
23
+ def after_insert; end
24
+ end
25
+
26
+ def self.included(mod)
27
+ mod.class_eval do
28
+ include InstanceMethods
29
+ extend ClassMethods
30
+ end
31
+ end
32
+
33
+ class Metadata < Hash
34
+ X_AMZ_META = 'x-amz-meta-'
35
+
36
+ def initialize(object)
37
+ super()
38
+ @object = object
39
+ decode(@object.header)
40
+ end
41
+
42
+ def decode(header)
43
+ header.select do |key, val|
44
+ key.match(/^#{X_AMZ_META}/)
45
+ end.each do |key, val|
46
+ self[key.sub(X_AMZ_META, '')] = begin
47
+ a = val.split(',').map do |val|
48
+ RAWS.unescape(val)
49
+ end
50
+ 1 < a.size ? a : a.first
51
+ end
52
+ end
53
+ end
54
+
55
+ def encode
56
+ self.inject({}) do |ret, (key, val)|
57
+ key = X_AMZ_META + key
58
+
59
+ if val.is_a? Array
60
+ ret[key] = val.map do |v|
61
+ RAWS.escape(v.strip)
62
+ end.join(',')
63
+ else
64
+ ret[key] = RAWS.escape(val.strip)
65
+ end
66
+
67
+ ret
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,3 @@
1
+ class RAWS::S3::S3Object
2
+ include ::RAWS::S3::Model
3
+ end