simple_aws 0.0.1b → 0.0.1c

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -106,6 +106,7 @@ Implemented APIs
106
106
 
107
107
  These are the following Amazon APIs that SimpleAWS currently handles:
108
108
 
109
+ * S3
109
110
  * EC2
110
111
  * ELB
111
112
  * IAM
@@ -125,7 +126,6 @@ These are the following Amazon APIs that SimpleAWS currently handles:
125
126
  Yet to be Implemented
126
127
  ---------------------
127
128
 
128
- * S3
129
129
  * CloudFront
130
130
 
131
131
  Currently Out-Of-Scope
@@ -1,4 +1,5 @@
1
1
  require 'httparty'
2
+ require 'httmultiparty'
2
3
  require 'openssl'
3
4
 
4
5
  require 'aws/core/response'
@@ -6,7 +7,7 @@ require 'aws/core/response'
6
7
  module AWS
7
8
 
8
9
  class HTTP
9
- include HTTParty
10
+ include HTTMultiParty
10
11
  format :xml
11
12
  end
12
13
 
@@ -24,7 +25,8 @@ module AWS
24
25
  HTTP.send(request.method,
25
26
  request.uri,
26
27
  :query => request.params,
27
- :headers => request.headers
28
+ :headers => request.headers,
29
+ :body => request.body
28
30
  )
29
31
  )
30
32
  end
@@ -111,6 +111,13 @@ module AWS
111
111
  ##
112
112
  attr_reader :headers
113
113
 
114
+ ##
115
+ # Raw string data to be put in the body of the request.
116
+ # Body can also be an IO object (something that response to #read) and
117
+ # if so the request will stream the file to the server.
118
+ ##
119
+ attr_accessor :body
120
+
114
121
  ##
115
122
  # Set up a new Request for the given +host+ and +path+ using the given
116
123
  # http +method+ (:get, :post, :put, :delete).
@@ -146,8 +146,11 @@ module AWS
146
146
  end
147
147
 
148
148
  def value_or_proxy(value)
149
- if value.is_a?(Hash) || value.is_a?(Array)
149
+ case value
150
+ when Hash
150
151
  ResponseProxy.new value
152
+ when Array
153
+ value.map {|v| ResponseProxy.new v }
151
154
  else
152
155
  value
153
156
  end
@@ -159,27 +162,36 @@ module AWS
159
162
  ##
160
163
  attr_reader :body
161
164
 
165
+ ##
166
+ # HTTP Status code of the response
167
+ ##
168
+ attr_reader :code
169
+
170
+ ##
171
+ # Hash of headers found in the response
172
+ ##
173
+ attr_reader :headers
174
+
162
175
  def initialize(http_response)
163
176
  if !http_response.success?
164
- error = parse_error_from http_response.parsed_response
165
- raise UnsuccessfulResponse.new(
166
- http_response.code,
167
- error["Code"],
168
- error["Message"]
169
- )
177
+ parse_and_throw_error_from http_response
170
178
  end
171
179
 
180
+ @code = http_response.code
172
181
  @body = http_response.parsed_response
182
+ @headers = http_response.headers
173
183
 
174
- inner = @body[@body.keys.first]
175
- response_root =
176
- if result_key = inner.keys.find {|k| k =~ /Result$/}
177
- inner[result_key]
178
- else
179
- inner
180
- end
184
+ if @body
185
+ inner = @body[@body.keys.first]
186
+ response_root =
187
+ if result_key = inner.keys.find {|k| k =~ /Result$/}
188
+ inner[result_key]
189
+ else
190
+ inner
191
+ end
181
192
 
182
- @request_root = ResponseProxy.new response_root
193
+ @request_root = ResponseProxy.new response_root
194
+ end
183
195
  end
184
196
 
185
197
  ##
@@ -216,9 +228,29 @@ module AWS
216
228
 
217
229
  protected
218
230
 
231
+ def parse_and_throw_error_from(http_response)
232
+ if http_response.parsed_response
233
+ error = parse_error_from http_response.parsed_response
234
+ else
235
+ error = { "Message" => http_response.response }
236
+ end
237
+
238
+ raise UnsuccessfulResponse.new(
239
+ http_response.code,
240
+ error["Code"],
241
+ error["Message"]
242
+ )
243
+ end
244
+
219
245
  def parse_error_from(body)
220
246
  if body.has_key? "ErrorResponse"
221
247
  body["ErrorResponse"]["Error"]
248
+ elsif body.has_key? "Error"
249
+ if body["Error"]["StringToSign"]
250
+ body["Error"]["Message"] += " String to Sign: #{body["Error"]["StringToSign"].inspect}"
251
+ end
252
+
253
+ body["Error"]
222
254
  elsif body.has_key? "Response"
223
255
  body["Response"]["Errors"]["Error"]
224
256
  else
data/lib/aws/s3.rb ADDED
@@ -0,0 +1,127 @@
1
+ require 'aws/api'
2
+ require 'aws/signing/authorization_header'
3
+
4
+ module AWS
5
+
6
+ ##
7
+ # Amazon's Simple Storage Service
8
+ #
9
+ # http://docs.amazonwebservices.com/AmazonS3/latest/API/Welcome.html
10
+ #
11
+ # As S3 is much closer to a RESTful service than the other AWS APIs, all
12
+ # calls through this API are done through the four handled HTTP METHODS:
13
+ # GET, PUT, DELETE, POST and HEAD. When sending a request, follow exactly what
14
+ # is described in the AWS API docs in the link above.
15
+ #
16
+ # So "GET Service" is
17
+ #
18
+ # s3.get "/"
19
+ #
20
+ # When working with a specific bucket, pass in :bucket after the path:
21
+ #
22
+ # s3.get "/", :bucket => "bucket_name"
23
+ #
24
+ # s3.get "/?policy", :bucket => "bucket_name"
25
+ #
26
+ # For requests that need extra parameters, use the :params option:
27
+ #
28
+ # s3.get "/object/name", :bucket => "bucket_name", :params => {
29
+ # "response-content-disposition" => "attachment"
30
+ # }
31
+ #
32
+ # Also use params in the cases that AWS asks for form fields, such as
33
+ # "POST Object".
34
+ #
35
+ # A lot of S3 communication happens through request and response headers.
36
+ # To specify a certian set of headers on the request, use :headers:
37
+ #
38
+ # s3.get "/", :bucket => "bucket_name", :headers => {
39
+ # "x-amz-security-token" => "security string"
40
+ # }
41
+ #
42
+ # Many of the PUT requests require a body of some sort, sometimes XML,
43
+ # sometimes JSON, and other times the raw file data. Use :body for this
44
+ # information. :body is expected to be either a String containing the XML or
45
+ # JSON information, or an object that otherwise response to #read for file
46
+ # uploads. This API does not build XML or JSON for you right now.
47
+ #
48
+ # s3.put "/object/name.txt", :bucket => "bucket_name", :body => {:file => File.open()}
49
+ #
50
+ # As this is a common use case, if you don't have any more parameters to send
51
+ # with the file being uploaded, just use :file.
52
+ #
53
+ # s3.put "/object/name.txt", :bucket => "bucket_name", :file => File.open()
54
+ #
55
+ # This API does ensure that file data is uploaded as efficiently as possible,
56
+ # streaming file data from disc to AWS without blowing up memory. All files are
57
+ # uploading using multipart/form-data.
58
+ #
59
+ # NOTE: Like the other parts of SimpleAWS, this API does NOT try to make the
60
+ # AWS API better, but simply provides a cleaner, easy to use API for Ruby.
61
+ # As such, this API does not offer streaming downloads of file data from S3.
62
+ # That is up to you to implement at this time, by running a HEAD to get
63
+ # Content-Length then repeated GETs using the "Range:bytes" header to specify
64
+ # which parts to download next.
65
+ #
66
+ # Raw file data in a response will be available in the #body method on the Response
67
+ # returned by the method call.
68
+ ##
69
+ class S3 < API
70
+ endpoint "s3"
71
+ use_https true
72
+ version "2006-03-01"
73
+
74
+ [:get, :post, :put, :delete, :head].each do |method|
75
+ define_method(method) do |*args|
76
+ self.call method, *args
77
+ end
78
+ end
79
+
80
+ def call(method, path, options = {})
81
+ if options[:bucket]
82
+ path = path.gsub(/^\//, "/#{options[:bucket]}/")
83
+ end
84
+
85
+ request = AWS::Request.new method, self.uri, path
86
+
87
+ (options[:params] || {}).each do |k, v|
88
+ request.params[k] = v
89
+ end
90
+
91
+ (options[:headers] || {}).each do |k, v|
92
+ request.headers[k] = v
93
+ end
94
+
95
+ if options[:file]
96
+ options[:body] = {:file => options[:file]}
97
+ end
98
+
99
+ request.body = options[:body]
100
+
101
+ if request.body.is_a?(Hash) && request.body[:file]
102
+ request.headers["Content-Type"] =
103
+ "multipart/form-data; boundary=-----------RubyMultipartPost"
104
+ end
105
+
106
+ connection = AWS::Connection.new
107
+ connection.call finish_and_sign_request(request)
108
+ end
109
+
110
+ include Signing::AuthorizationHeader
111
+
112
+ ##
113
+ # S3 handles region endpoints a little differently
114
+ ##
115
+ def uri
116
+ return @uri if @uri
117
+
118
+ @uri = @use_https ? "https" : "http"
119
+ @uri += "://#{@endpoint}"
120
+ @uri += "-#{@region}" if @region
121
+ @uri += ".amazonaws.com"
122
+ @uri
123
+ end
124
+
125
+ end
126
+
127
+ end
@@ -0,0 +1,43 @@
1
+ require 'openssl'
2
+
3
+ module AWS
4
+ module Signing
5
+ ##
6
+ # Implementation of signing using the Authorization header, as used by S3 and CloudFront
7
+ ##
8
+ module AuthorizationHeader
9
+
10
+ ##
11
+ # Build and sign the final request, as per the rules here:
12
+ # http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html
13
+ ##
14
+ def finish_and_sign_request(request)
15
+ request.headers["Date"] = Time.now.utc.httpdate
16
+ request.headers["Authorization"] =
17
+ "AWS #{self.access_key}:#{Base64.encode64(build_signature_for(request)).chomp}"
18
+
19
+ request
20
+ end
21
+
22
+ def build_signature_for(request)
23
+ amazon_headers = request.headers.select {|k, v|
24
+ k =~ /^x-amz/i
25
+ }.map {|k, v|
26
+ "#{k.downcase}:#{v}".chomp
27
+ }
28
+
29
+ to_sign = [
30
+ request.method.to_s.upcase,
31
+ request.headers["Content-Md5"] || "",
32
+ request.headers["Content-Type"] || "",
33
+ request.headers["Date"],
34
+ amazon_headers,
35
+ request.path
36
+ ].flatten.join("\n")
37
+
38
+ OpenSSL::HMAC.digest("sha1", self.secret_key, to_sign)
39
+ end
40
+
41
+ end
42
+ end
43
+ end
data/samples/s3.rb ADDED
@@ -0,0 +1,64 @@
1
+ $: << File.expand_path("../../lib", __FILE__)
2
+
3
+ require 'aws/s3'
4
+
5
+ ##
6
+ # Expects your Amazon keys to be in the environment, something like
7
+ #
8
+ # export AWS_KEY="KEY"
9
+ # export AWS_SECRET="SECRET"
10
+ #
11
+ # Usage:
12
+ # ruby sample/s3.rb [bucket name] [file to use]
13
+ #
14
+ # This script will upload the file, show that the file is up, then remove the file
15
+ ##
16
+
17
+ def bad_usage
18
+ puts ""
19
+ puts "Usage:"
20
+ puts " ruby sample/s3.rb [bucket name] [file to use]"
21
+ exit 1
22
+ end
23
+
24
+ s3 = AWS::S3.new ENV["AWS_KEY"], ENV["AWS_SECRET"]
25
+
26
+ bucket_name = ARGV[0]
27
+ file_name = ARGV[1]
28
+
29
+ puts "All buckets in this account:", ""
30
+
31
+ s3.get("/").buckets.bucket.each do |bucket|
32
+ puts bucket.name
33
+ end
34
+
35
+ puts "", "First 10 files in #{bucket_name}:", ""
36
+
37
+ bad_usage unless bucket_name
38
+
39
+ s3.get("/", :bucket => bucket_name, :params => {"max-keys" => 10}).contents.each do |entry|
40
+ puts entry.key
41
+ end
42
+
43
+ puts "", "Uploading #{file_name} to #{bucket_name}:", ""
44
+
45
+ bad_usage unless file_name
46
+ uploaded_file_name = File.basename file_name
47
+
48
+ p s3.put("/#{uploaded_file_name}", :bucket => bucket_name, :file => File.open(file_name))
49
+
50
+ puts "", "Checking that the file now exists...", ""
51
+
52
+ p s3.head("/#{uploaded_file_name}", :bucket => bucket_name)
53
+
54
+ puts "", "Deleting the file from S3", ""
55
+
56
+ p s3.delete("/#{uploaded_file_name}", :bucket => bucket_name)
57
+
58
+ puts "", "Checking that file is no longer in S3...", ""
59
+
60
+ begin
61
+ p s3.head("/#{uploaded_file_name}", :bucket => bucket_name)
62
+ rescue => ex
63
+ puts "Not found: #{ex.message}"
64
+ end
data/simple_aws.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "simple_aws"
3
- s.version = "0.0.1b"
3
+ s.version = "0.0.1c"
4
4
  s.platform = Gem::Platform::RUBY
5
5
  s.authors = ["Jason Roelofs"]
6
6
  s.email = ["jameskilton@gmail.com"]
@@ -12,6 +12,7 @@ Gem::Specification.new do |s|
12
12
 
13
13
  s.add_dependency "ox"
14
14
  s.add_dependency "httparty"
15
+ s.add_dependency "httmultiparty"
15
16
 
16
17
  s.add_dependency "jruby-openssl" if RUBY_PLATFORM == 'java'
17
18
 
@@ -56,5 +56,17 @@ describe AWS::Connection do
56
56
  @connection.call request
57
57
  end
58
58
 
59
+ it "passes through any body on the Request" do
60
+ request = AWS::Request.new(:get, "host.com", "/")
61
+ request.body = "This is some body text"
62
+
63
+ AWS::HTTP.expects(:get).with {|uri, options|
64
+ options[:query].wont_be_nil
65
+ options[:body].must_equal "This is some body text"
66
+ }.returns(@http_response)
67
+
68
+ @connection.call request
69
+ end
70
+
59
71
  end
60
72
  end
@@ -19,13 +19,6 @@ describe AWS::Request do
19
19
  @request.method.must_equal :get
20
20
  end
21
21
 
22
- it "can be given parameters to pass in" do
23
- @request.params["Param1"] = "Value1"
24
- @request.params["Param2"] = "Value2"
25
-
26
- @request.params.must_equal "Param1" => "Value1", "Param2" => "Value2"
27
- end
28
-
29
22
  it "ensures path is never an empty string" do
30
23
  @request.path = ""
31
24
  @request.path.must_equal "/"
@@ -38,6 +31,22 @@ describe AWS::Request do
38
31
  end
39
32
  end
40
33
 
34
+ describe "parameters" do
35
+ it "can be given parameters to pass in" do
36
+ @request.params["Param1"] = "Value1"
37
+ @request.params["Param2"] = "Value2"
38
+
39
+ @request.params.must_equal "Param1" => "Value1", "Param2" => "Value2"
40
+ end
41
+ end
42
+
43
+ describe "body" do
44
+ it "can be given raw body text" do
45
+ @request.body = "BODY!"
46
+ @request.body.must_equal "BODY!"
47
+ end
48
+ end
49
+
41
50
  describe "hashes" do
42
51
  it "converts hash params to AWS param names" do
43
52
  @request.params["Filter"] = [
@@ -8,6 +8,7 @@ describe AWS::Response do
8
8
  before do
9
9
  @error_response = {}
10
10
  @http_response = stub
11
+ @http_response.stubs(:headers).returns(nil)
11
12
  @http_response.stubs(:success?).returns(false)
12
13
  @http_response.stubs(:code).returns(401)
13
14
  end
@@ -55,6 +56,25 @@ describe AWS::Response do
55
56
  error.message.must_equal "AuthFailure (401): Message about failing to authenticate"
56
57
  end
57
58
 
59
+ it "handles S3 errors" do
60
+ @error_response = { "Error" => {
61
+ "Code" => "AuthFailure", "Message" => "OH snap!",
62
+ "StringToSign" => "SOME STRING"
63
+ } }
64
+ @http_response.stubs(:parsed_response).returns(@error_response)
65
+
66
+ error =
67
+ lambda {
68
+ AWS::Response.new @http_response
69
+ }.must_raise AWS::UnsuccessfulResponse
70
+
71
+ error.code.must_equal 401
72
+ error.error_type.must_equal "AuthFailure"
73
+ error.error_message.must_equal "OH snap! String to Sign: \"SOME STRING\""
74
+
75
+ error.message.must_equal "AuthFailure (401): OH snap! String to Sign: \"SOME STRING\""
76
+ end
77
+
58
78
  it "raises if it can't parse the error message" do
59
79
  @error_response = { "Erroring" => "This is an error message" }
60
80
  @http_response.stubs(:parsed_response).returns(@error_response)
@@ -66,6 +86,19 @@ describe AWS::Response do
66
86
 
67
87
  error.message.must_match /Unable to parse error code from/
68
88
  end
89
+
90
+ it "handles errors that have no body to parse" do
91
+ @http_response.stubs(:code).returns(404)
92
+ @http_response.stubs(:parsed_response).returns(nil)
93
+ @http_response.stubs(:response).returns("This is a response ok?")
94
+
95
+ error = lambda {
96
+ response = AWS::Response.new @http_response
97
+ }.must_raise AWS::UnsuccessfulResponse
98
+
99
+ error.code.must_equal 404
100
+ error.message.must_equal " (404): This is a response ok?"
101
+ end
69
102
  end
70
103
 
71
104
  describe "successful response parsing and mapping" do
@@ -79,6 +112,8 @@ describe AWS::Response do
79
112
  }
80
113
 
81
114
  @http_response = stub
115
+ @http_response.stubs(:headers).returns(nil)
116
+ @http_response.stubs(:code).returns(200)
82
117
  @http_response.stubs(:success?).returns(true)
83
118
  @http_response.stubs(:parsed_response).returns(@response_hash)
84
119
 
@@ -104,6 +139,23 @@ describe AWS::Response do
104
139
  @response["unknownKey"].must_be_nil
105
140
  end
106
141
 
142
+ it "handles responses with no body" do
143
+ @http_response.stubs(:parsed_response).returns(nil)
144
+ response = AWS::Response.new @http_response
145
+ response.body.must_be_nil
146
+ end
147
+
148
+ it "knows the status code of the response" do
149
+ @response.code.must_equal 200
150
+ end
151
+
152
+ it "pulls out any response headers" do
153
+ @http_response.stubs(:headers).returns({"Header1" => "Value2"})
154
+ response = AWS::Response.new @http_response
155
+
156
+ response.headers.must_equal "Header1" => "Value2"
157
+ end
158
+
107
159
  end
108
160
 
109
161
  describe "deeply nested response/results objects" do
@@ -119,6 +171,8 @@ describe AWS::Response do
119
171
  }
120
172
 
121
173
  @http_response = stub
174
+ @http_response.stubs(:headers).returns(nil)
175
+ @http_response.stubs(:code).returns(202)
122
176
  @http_response.stubs(:success?).returns(true)
123
177
  @http_response.stubs(:parsed_response).returns(@response_hash)
124
178
 
@@ -167,11 +221,20 @@ describe AWS::Response do
167
221
  "withMemberSet" => {
168
222
  "member" => {"keyId" => "4567"}
169
223
  },
170
- "UpperCamelKey" => "purple dog"
224
+ "UpperCamelKey" => "purple dog",
225
+ "Buckets" => {
226
+ "Bucket" => [
227
+ {"Name" => "bucket1"},
228
+ {"Name" => "bucket2"},
229
+ {"Name" => "bucket3"}
230
+ ]
231
+ }
171
232
  }
172
233
  }
173
234
 
174
235
  @http_response = stub
236
+ @http_response.stubs(:code).returns(202)
237
+ @http_response.stubs(:headers).returns(nil)
175
238
  @http_response.stubs(:success?).returns(true)
176
239
  @http_response.stubs(:parsed_response).returns(@response_hash)
177
240
 
@@ -226,6 +289,12 @@ describe AWS::Response do
226
289
  @response.upper_camel_key.must_equal "purple dog"
227
290
  end
228
291
 
292
+ it "works with straight array responses" do
293
+ @response.buckets.bucket[0].name.must_equal "bucket1"
294
+ @response.buckets.bucket[1].name.must_equal "bucket2"
295
+ @response.buckets.bucket[2].name.must_equal "bucket3"
296
+ end
297
+
229
298
  end
230
299
 
231
300
  describe "hash keys" do
@@ -259,6 +328,12 @@ describe AWS::Response do
259
328
  it "also squashes the 'member' tag" do
260
329
  @response["withMemberSet"][0]["keyId"].must_equal "4567"
261
330
  end
331
+
332
+ it "works with straight array responses" do
333
+ @response["Buckets"]["Bucket"][0]["Name"].must_equal "bucket1"
334
+ @response["Buckets"]["Bucket"][1]["Name"].must_equal "bucket2"
335
+ @response["Buckets"]["Bucket"][2]["Name"].must_equal "bucket3"
336
+ end
262
337
  end
263
338
 
264
339
  end
@@ -266,6 +341,8 @@ describe AWS::Response do
266
341
  describe "#request_id" do
267
342
  before do
268
343
  @http_response = stub
344
+ @http_response.stubs(:headers).returns(nil)
345
+ @http_response.stubs(:code).returns(200)
269
346
  @http_response.stubs(:success?).returns(true)
270
347
  end
271
348
 
@@ -0,0 +1,108 @@
1
+ require 'test_helper'
2
+ require 'aws/s3'
3
+
4
+ describe AWS::S3 do
5
+
6
+ before do
7
+ @api = AWS::S3.new "key", "secret"
8
+ end
9
+
10
+ it "points to the endpoint" do
11
+ @api.uri.must_equal "https://s3.amazonaws.com"
12
+ end
13
+
14
+ it "properly builds region endpoints" do
15
+ api = AWS::S3.new "key", "secret", "us-west-1"
16
+ api.uri.must_equal "https://s3-us-west-1.amazonaws.com"
17
+ end
18
+
19
+ it "works with the current version" do
20
+ @api.version.must_equal "2006-03-01"
21
+ end
22
+
23
+ describe "API calls" do
24
+
25
+ [:get, :post, :put, :delete, :head].each do |method|
26
+ it "supports the #{method} HTTP method" do
27
+ AWS::Connection.any_instance.expects(:call).with do |request|
28
+ request.method.must_equal method
29
+ request.host.must_equal "https://s3.amazonaws.com"
30
+ request.path.must_equal "/"
31
+ true
32
+ end
33
+
34
+ @api.send method, "/"
35
+ end
36
+ end
37
+
38
+ it "rebuilds the host if :bucket given" do
39
+ AWS::Connection.any_instance.expects(:call).with do |request|
40
+ request.path.must_equal "/bucket-name/"
41
+ request.host.must_equal "https://s3.amazonaws.com"
42
+ true
43
+ end
44
+
45
+ @api.get "/", :bucket => "bucket-name"
46
+ end
47
+
48
+ it "takes parameters" do
49
+ AWS::Connection.any_instance.expects(:call).with do |request|
50
+ request.params["Parameter1"].must_equal "Value2"
51
+ true
52
+ end
53
+
54
+ @api.get "/", :params => { "Parameter1" => "Value2" }
55
+ end
56
+
57
+ it "takes extra headers" do
58
+ AWS::Connection.any_instance.expects(:call).with do |request|
59
+ request.headers["Header14"].must_equal "Out to Lunch"
60
+ true
61
+ end
62
+
63
+ @api.get "/", :headers => { "Header14" => "Out to Lunch" }
64
+ end
65
+
66
+ it "takes a raw body" do
67
+ AWS::Connection.any_instance.expects(:call).with do |request|
68
+ request.body.must_equal "This is a body of text"
69
+ true
70
+ end
71
+
72
+ @api.get "/", :body => "This is a body of text"
73
+ end
74
+
75
+ it "adds the form-data header if the body has a file in it" do
76
+ AWS::Connection.any_instance.expects(:call).with do |request|
77
+ request.body.must_equal :file => "This is a body of text"
78
+ request.headers["Content-Type"].must_equal(
79
+ "multipart/form-data; boundary=-----------RubyMultipartPost"
80
+ )
81
+ true
82
+ end
83
+
84
+ @api.get "/", :body => {:file => "This is a body of text"}
85
+ end
86
+
87
+ it "allows use of :file if :body only contains a file" do
88
+ AWS::Connection.any_instance.expects(:call).with do |request|
89
+ request.body.must_equal :file => "This is a body of text"
90
+ request.headers["Content-Type"].must_equal(
91
+ "multipart/form-data; boundary=-----------RubyMultipartPost"
92
+ )
93
+ true
94
+ end
95
+
96
+ @api.get "/", :file => "This is a body of text"
97
+ end
98
+
99
+ it "signs the request using the Authorization header" do
100
+ AWS::Connection.any_instance.expects(:call).with do |request|
101
+ request.headers["Authorization"].wont_be_nil
102
+ true
103
+ end
104
+
105
+ @api.get "/"
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,33 @@
1
+ require 'test_helper'
2
+ require 'aws/api'
3
+ require 'aws/call_types/action_param'
4
+ require 'aws/signing/authorization_header'
5
+
6
+ describe AWS::Signing::AuthorizationHeader do
7
+
8
+ class SigningAuthHeaderTestAPI < AWS::API
9
+ endpoint "aptest"
10
+ version "2011-01-01"
11
+ use_https true
12
+
13
+ include AWS::CallTypes::ActionParam
14
+ include AWS::Signing::AuthorizationHeader
15
+ end
16
+
17
+ it "signs the given request according to Version 3 rules" do
18
+ AWS::Connection.any_instance.expects(:call).with do |request|
19
+ header = request.headers["Authorization"]
20
+ parts = header.split(":")
21
+
22
+ parts[0].must_equal "AWS key"
23
+ parts[1].wont_be_nil
24
+
25
+ Time.parse(request.headers["Date"]).wont_be_nil
26
+ true
27
+ end.returns
28
+
29
+ obj = SigningAuthHeaderTestAPI.new "key", "secret"
30
+ obj.describe_instances
31
+ end
32
+
33
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_aws
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1b
4
+ version: 0.0.1c
5
5
  prerelease: 5
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-01-03 00:00:00.000000000 Z
12
+ date: 2012-01-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ox
16
- requirement: &70137915318080 !ruby/object:Gem::Requirement
16
+ requirement: &70146086124160 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70137915318080
24
+ version_requirements: *70146086124160
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: httparty
27
- requirement: &70137915317640 !ruby/object:Gem::Requirement
27
+ requirement: &70146086123740 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,18 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70137915317640
35
+ version_requirements: *70146086123740
36
+ - !ruby/object:Gem::Dependency
37
+ name: httmultiparty
38
+ requirement: &70146086123280 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70146086123280
36
47
  description: The simplest and easiest to use and maintain AWS communication library
37
48
  email:
38
49
  - jameskilton@gmail.com
@@ -63,7 +74,9 @@ files:
63
74
  - lib/aws/map_reduce.rb
64
75
  - lib/aws/mechanical_turk.rb
65
76
  - lib/aws/rds.rb
77
+ - lib/aws/s3.rb
66
78
  - lib/aws/ses.rb
79
+ - lib/aws/signing/authorization_header.rb
67
80
  - lib/aws/signing/version2.rb
68
81
  - lib/aws/signing/version3.rb
69
82
  - lib/aws/sns.rb
@@ -71,6 +84,7 @@ files:
71
84
  - samples/ec2.rb
72
85
  - samples/elb.rb
73
86
  - samples/iam.rb
87
+ - samples/s3.rb
74
88
  - samples/sqs.rb
75
89
  - samples/turk.rb
76
90
  - simple_aws.gemspec
@@ -91,7 +105,9 @@ files:
91
105
  - test/aws/map_reduce_test.rb
92
106
  - test/aws/mechanical_turk_test.rb
93
107
  - test/aws/rds_test.rb
108
+ - test/aws/s3_test.rb
94
109
  - test/aws/ses.rb
110
+ - test/aws/signing/authorization_header_test.rb
95
111
  - test/aws/signing/version2_test.rb
96
112
  - test/aws/signing/version3.rb
97
113
  - test/aws/sns_test.rb
@@ -139,7 +155,9 @@ test_files:
139
155
  - test/aws/map_reduce_test.rb
140
156
  - test/aws/mechanical_turk_test.rb
141
157
  - test/aws/rds_test.rb
158
+ - test/aws/s3_test.rb
142
159
  - test/aws/ses.rb
160
+ - test/aws/signing/authorization_header_test.rb
143
161
  - test/aws/signing/version2_test.rb
144
162
  - test/aws/signing/version3.rb
145
163
  - test/aws/sns_test.rb