simple_aws 1.0.0.pre1 → 1.0.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,40 +1,36 @@
1
1
  SimpleAWS [![Travis CI Build Status](https://secure.travis-ci.org/jameskilton/simple_aws.png)](http://travis-ci.org/jameskilton/simple_aws)
2
2
  =========
3
3
 
4
- A thin, simple, forward compatible Ruby wrapper around the various Amazon AWS APIs. Unless otherwise mentioned below, this library will wrap every API available service listed on this page: http://aws.amazon.com/documentation/
4
+ A thin, simple, forward compatible Ruby wrapper around the various Amazon Web Service APIs.
5
5
 
6
6
  What?! Why?
7
7
  -----------
8
8
 
9
9
  Do we really need another Ruby library to talk to Amazon Web Services? Aren't there enough libraries out there that could just use some more help to make them better? What about [fog](http://fog.io), or [aws-sdk](http://rubygems.org/gems/aws-sdk), or [aws](http://rubygems.org/gems/aws), or [right_aws](http://rubygems.org/gems/right_aws)?
10
10
 
11
- While there are a number of well used libraries, I feel they have all fallen prey to the same two problems: complexity and forward incompatibility.
11
+ While there are a number of well used libraries, I feel they have all fallen prey to the same two problems: they are far too complex for what they are and they all lack forward compatibility.
12
12
 
13
13
  ### Complexity
14
14
 
15
- Every Ruby AWS library in use today is simply too complex. Every library I've tried to use has ended up hurting my productivity as I often have to dive into the code to find out what the parameter list is, what object I need to work with, or what hash keys map to the actual AWS API parameters. Every library that tries to build an Object Abstraction wrapper on top of AWS's APIs suffers from leaky abstractions, which results in yet more time lost trying to figure out what needs to be called, with what, and what gets returned. Software is supposed to be simple, it's supposed to make your life easier. I've yet to find an AWS library that does this.
15
+ Every Ruby AWS library in use today is simply too complex. Each one I've tried to use has ended up hurting my productivity as I often found myself diving into the library's code to figure out how to call the API method in question. Instead of just working with Amazon's API, I end up fighting the library, constantly having to re-learn whatever abstraction said library is trying to provide. Every library mentioned either hard-codes parameter lists, has it's own mapping from hash keys to AWS parameters, or wraps up an Object API around everything, leading to confusion and more lost productivity when that abstraction leaks. Software is supposed to be simple to use; it's supposed to make your life easier. I've yet to find an AWS library that does this.
16
16
 
17
17
  ### Forward Compatibility
18
18
 
19
- Ignoring the complexity argument above, what finally drove me to create this library is the complete lack of forward compatibility in all existing Ruby AWS libraries. Any time I wanted to use a new parameter, new action, or new API, I would need to jump into the library itself and implement the missing pieces. In the usual OSS circles this doesn't sound that bad, and is in fact praised, but when you're dealing with an API library, this requirement quickly becomes a frustration.
19
+ Outside of the pervasive complexity of these libraries, what finally drove me to create this library is the complete lack of forward compatibility in all of them. Any time I wanted to use a new parameter, new action, or new API, I would need to jump into the library itself to implement the missing pieces. In normal OSS fashion, this is of course to be lauded, contributing back to libraries is what makes software better. However, in the case of API wrappers, this very quickly becomes a frustration.
20
20
 
21
- Amazon constantly updates AWS APIs, adding parameters and actions, and at times entire new APIs. An AWS library should work *with* the API in question, not fight against it. The only thing a hard-coded parameter list does is add confusion as you have to keep two things in your mind: what you want to call, and how the library lets you call it. SimpleAWS simply says no, it won't force anything on the user. Use the names of the API methods and parameters and them alone. If a new parameter is added to the API you're using, just use it; SimpleAWS doesn't care, it will just work.
21
+ Amazon constantly updates AWS APIs, adding parameters and actions, and at times entire new APIs. An AWS library should work *with* the API in question, not fight against it. The only thing a hard-coded parameter list does is add confusion. When you have to figure out how AWS parameters map to library parameters, or hash keys, your productivity drops. When you have to figure out how an object is calling an AWS library, and how you're supposed to use that object, your productivity drops. Likewise when you finally realize that the library does not currently support the action, parameter, or API you're trying to use at the time, your productivity is now at a complete stop.
22
22
 
23
- The name SimpleAWS isn't a wish or hope, it's the core philosophy. This library focuses on being a very thin communication layer between your Ruby code and Amazon's AWS APIs. Let SimpleAWS handle the messy communication details so your code can do what it needs to do letting you be more productive.
24
-
25
- In short, it's the Unix philosophy, SimpleAWS does one thing and does it well and nothing else.
23
+ SimpleAWS simply says no, no more leaky abstractions and confusing APIs. Just use the names of the API methods and parameters as defined in Amazon's documentation! If a new parameter is added to the API you're using, just use it. The name SimpleAWS isn't a wish or hope, it's the core philosophy. This library focuses on being a very thin communication layer between your Ruby code and Amazon's AWS APIs. Let SimpleAWS handle the messy communication details so your code can do what it needs to do letting you be more productive.
26
24
 
27
25
 
28
26
  Surely SimpleAWS isn't just `curl`?
29
27
  -----------------------------------
30
28
 
31
- It's well know that AWS has its share of warts and wtfs. SimpleAWS doesn't try to fix these, as that's the path towards being yet another over-complicated and rigid library that SimpleAWS is trying to solve.
32
-
33
- What SimpleAWS does do is add some logic to ensure it follows the Principle of Least Surprise.
29
+ It's well know that AWS has its share of warts and wtfs. SimpleAWS doesn't try to fix these. What SimpleAWS does do is add as little logic as possible to make you productive and to ensure it follows the Principle of Least Surprise.
34
30
 
35
31
  ### Calling
36
32
 
37
- First of all, calling actions are implemented as ruby methods, handled through mainly through `method_missing` (S3 and CloudFront are the two exceptions). You can call the AWS actions by AWSName or by ruby_name, they both work:
33
+ First of all, calling actions are implemented as ruby methods, handled through mainly through `method_missing` (S3 and CloudFront are the two current exceptions). You can call the AWS actions by AWSName or by ruby_name, they both work:
38
34
 
39
35
  ```ruby
40
36
  ec2 = AWS::EC2.new key, secret
@@ -50,7 +46,7 @@ ec2.DescribeInstances
50
46
 
51
47
  ### Parameters
52
48
 
53
- With that in mind, here's what SimpleAWS allows. The following three are equivalent:
49
+ Adding parameters to your method calls follows similar rules, with some Quality of Life improvements. The following three are equivalent:
54
50
 
55
51
  #### Just Call It
56
52
 
@@ -92,9 +88,9 @@ ec2.describe_instances({
92
88
 
93
89
  ### Response Parsing
94
90
 
95
- All requests return an AWS::Response which does a few cleanup tasks on the resulting XML to make it easier to query and to hide some of the worst warts an XML body tends to have.
91
+ All requests return an AWS::Response object which does a few cleanup tasks on the resulting XML to make it easier to query and to hide some of the worst warts an XML body tends to have.
96
92
 
97
- First of all, wherever AWS returns a list of items, they almost always get wrapped up in an `<item>` or `<member>` wrapper tag. AWS::Response gets rid of those tags and gives you a flat array to work with.
93
+ First of all, wherever AWS returns a list of items, they often get wrapped up in an `<item>` or `<member>` wrapper tag. AWS::Response gets rid of those tags and gives you a flat array to work with.
98
94
 
99
95
  Second, the resulting XML can have one or two wrapper objects that do nothing but encapsulate the information you're interested in. AWS::Response also jumps past these wrapper objects so you have direct access to the data in the response.
100
96
 
@@ -123,6 +119,11 @@ These are the Amazon APIs that SimpleAWS currently handles:
123
119
  * {AWS::SES SES}
124
120
  * {AWS::CloudFront CloudFront}
125
121
 
122
+ Not Currently Implemented
123
+ -------------------------
124
+
125
+ * DynamoDB (API docs aren't up yet, and the samples are hard to follow)
126
+
126
127
  Currently Out-Of-Scope
127
128
  ----------------------
128
129
 
data/lib/aws/api.rb CHANGED
@@ -11,12 +11,15 @@ module AWS
11
11
  # implementing various APIs:
12
12
  #
13
13
  # http://docs.amazonwebservices.com/general/latest/gr/index.html?rande.html
14
+ #
14
15
  ##
15
16
  class API
16
17
  class << self
17
18
 
18
19
  ##
19
20
  # Define the AWS endpoint for the API being wrapped.
21
+ #
22
+ # @param endpoint [String] Subdomain endpoint for this API. E.g. "s3" for Amazon's S3
20
23
  ##
21
24
  def endpoint(endpoint)
22
25
  @endpoint = endpoint
@@ -24,8 +27,8 @@ module AWS
24
27
 
25
28
  ##
26
29
  # Specify a default region for all requests for this API.
27
- # This region will be used if no region is given to the
28
- # constructor
30
+ #
31
+ # @param region [String] Specify the region this API defaults to
29
32
  ##
30
33
  def default_region(region)
31
34
  @default_region = region
@@ -35,13 +38,17 @@ module AWS
35
38
  # Specify whether this API uses HTTPS for requests. If not set,
36
39
  # the system will use HTTP. Some API endpoints are not available under
37
40
  # HTTP and some are only HTTP.
41
+ #
42
+ # @param value [Boolean] Set whether this API uses HTTPS by default or not
38
43
  ##
39
44
  def use_https(value)
40
45
  @use_https = value
41
46
  end
42
47
 
43
48
  ##
44
- # Specify the AWS version of the API in question. This will be a date string.
49
+ # Specify the AWS version of the API in question.
50
+ #
51
+ # @param version [String] The version this API currently uses.
45
52
  ##
46
53
  def version(version)
47
54
  @version = version
@@ -53,8 +60,10 @@ module AWS
53
60
 
54
61
  ##
55
62
  # Construct a new access object for the API in question.
56
- # +access_key+ and +secret_key+ are as defined in AWS security standards.
57
- # Use +region+ if you need to explicitly talk to a certain AWS region
63
+ #
64
+ # @param access_key [String] Amazon access key
65
+ # @param secret_key [String] Amazon secret key
66
+ # @param region [String] Give a specific region to talk to
58
67
  ##
59
68
  def initialize(access_key, secret_key, region = nil)
60
69
  @access_key = access_key
@@ -68,6 +77,8 @@ module AWS
68
77
 
69
78
  ##
70
79
  # Get the full host name for the current API
80
+ #
81
+ # @return [String] Full URI for this API
71
82
  ##
72
83
  def uri
73
84
  return @uri if @uri
@@ -63,12 +63,73 @@ module AWS
63
63
  super(key, secret)
64
64
  end
65
65
 
66
- [:get, :post, :put, :delete].each do |method|
67
- define_method(method) do |*args|
68
- self.call method, *args
69
- end
66
+ ##
67
+ # Send a request using HTTP GET
68
+ #
69
+ # @param path [String] The path of the resource at hand
70
+ # @param options [Hash] Options as defined above
71
+ #
72
+ # @return [AWS::Response] The results of the request
73
+ #
74
+ # @raise [AWS::UnsuccessfulResponse, AWS::UnknownErrorResponse] on response errors
75
+ ##
76
+ def get(path, options = {})
77
+ call :get, path, options
70
78
  end
71
79
 
80
+ ##
81
+ # Send a request using HTTP POST
82
+ #
83
+ # @param path [String] The path of the resource at hand
84
+ # @param options [Hash] Options as defined above
85
+ #
86
+ # @return [AWS::Response] The results of the request
87
+ #
88
+ # @raise [AWS::UnsuccessfulResponse, AWS::UnknownErrorResponse] on response errors
89
+ ##
90
+ def post(path, options = {})
91
+ call :post, path, options
92
+ end
93
+
94
+ ##
95
+ # Send a request using HTTP PUT
96
+ #
97
+ # @param path [String] The path of the resource at hand
98
+ # @param options [Hash] Options as defined above
99
+ #
100
+ # @return [AWS::Response] The results of the request
101
+ #
102
+ # @raise [AWS::UnsuccessfulResponse, AWS::UnknownErrorResponse] on response errors
103
+ ##
104
+ def put(path, options = {})
105
+ call :put, path, options
106
+ end
107
+
108
+ ##
109
+ # Send a request using HTTP DELETE
110
+ #
111
+ # @param path [String] The path of the resource at hand
112
+ # @param options [Hash] Options as defined above
113
+ #
114
+ # @return [AWS::Response] The results of the request
115
+ #
116
+ # @raise [AWS::UnsuccessfulResponse, AWS::UnknownErrorResponse] on response errors
117
+ ##
118
+ def delete(path, options = {})
119
+ call :delete, path, options
120
+ end
121
+
122
+ ##
123
+ # Execute an HTTP request against CloudFront.
124
+ #
125
+ # @param method [Symbol, String] The HTTP method to use
126
+ # @param path [String] The path of the resource at hand
127
+ # @param options [Hash] Options as defined above
128
+ #
129
+ # @return [AWS::Response] The results of the request
130
+ #
131
+ # @raise [AWS::UnsuccessfulResponse, AWS::UnknownErrorResponse] on response errors
132
+ ##
72
133
  def call(method, path, options = {})
73
134
  request = AWS::Request.new method, self.uri, "/#{self.version}#{path}"
74
135
 
@@ -29,8 +29,24 @@ end
29
29
 
30
30
  module AWS
31
31
 
32
+ ##
33
+ # Custom response parser to handle the various craziness of the AWS API
34
+ ##
35
+ class SimpleAWSParser < HTTParty::Parser
36
+ def parse
37
+ if supports_format?
38
+ super
39
+ elsif body =~ %r{<\?xml}
40
+ xml
41
+ else
42
+ body
43
+ end
44
+ end
45
+ end
46
+
32
47
  class HTTP
33
48
  include HTTParty
49
+ parser SimpleAWSParser
34
50
  end
35
51
 
36
52
  ##
@@ -10,7 +10,7 @@ module AWS
10
10
  # http://docs.amazonwebservices.com/AWSImportExport/latest/API/Welcome.html
11
11
  #
12
12
  # All requests are POST and always through HTTPS.
13
- # This API does not support region specifiers
13
+ # This API does not support region specifiers.
14
14
  #
15
15
  # @see AWS::CallTypes::ActionParam Calling rules
16
16
  # @see AWS::Response Response handling
data/lib/aws/s3.rb CHANGED
@@ -55,7 +55,13 @@ module AWS
55
55
  # As such, this API does not offer streaming downloads of file data from S3.
56
56
  # That is up to you to implement at this time, by running a HEAD to get
57
57
  # Content-Length then repeated GETs using the "Range:bytes" header to specify
58
- # which parts to download next.
58
+ # which parts to download next. You can see an example of this in samples/s3_batch_download.rb.
59
+ #
60
+ # Quality of Life note: if you forget the leading / (forward slash) in the path
61
+ # of a resource when# working with a bucket, this library will recognize this and
62
+ # fix the path for you. Thus, the following is also a valid call:
63
+ #
64
+ # s3.put "object/name.txt", :bucket => "bucket_name", :body => File.open()
59
65
  #
60
66
  # Raw file data in a response will be available in the #body method on the Response
61
67
  # returned by the method call.
@@ -67,12 +73,18 @@ module AWS
67
73
 
68
74
  ##
69
75
  # Build a full URL for the resource at +path+.
70
- # If options includes :expires, this url will be a signed url. :expires
71
- # needs to be the raw Unix timestamp at which this URL will expire, as
72
- # defined in the S3 documentation.
73
76
  #
74
- # Otherwise, +options+ can take anything as described above, but it
75
- # will not use :headers or anything related to :body.
77
+ # @param path [String] The path of the resource that needs a URL
78
+ # @param options [Hash] Options on how this URL will be generated.
79
+ #
80
+ # If options includes +:expires+, this url will be a signed url. +:expires+
81
+ # needs to be the raw Unix timestamp at which this URL will expire, as
82
+ # defined in the S3 documentation.
83
+ #
84
+ # Otherwise, +options+ can take anything as described above, but it
85
+ # will not use +:headers+ or anything related to +:body+.
86
+ #
87
+ # @return [String] The URL to the requested resource
76
88
  ##
77
89
  def url_for(path, options = {})
78
90
  request = build_request(:get, path, options)
@@ -88,7 +100,8 @@ module AWS
88
100
 
89
101
  if expires_at = options[:expires]
90
102
  # Small hack, expires is in the Date section of the
91
- # signing string, so we just do that here
103
+ # signing string, so we just do that here so that we don't
104
+ # muddy up build_signature_for
92
105
  request.headers["Date"] = expires_at.to_i
93
106
 
94
107
  signature = "Signature=#{build_signature_for(request)}"
@@ -101,18 +114,92 @@ module AWS
101
114
  url
102
115
  end
103
116
 
104
- [:get, :put, :delete, :head].each do |method|
105
- define_method(method) do |*args|
106
- request = self.build_request method, *args
117
+ ##
118
+ # Send a request using HTTP GET
119
+ #
120
+ # @param path [String] The path of the resource at hand
121
+ # @param options [Hash] Options as defined above
122
+ #
123
+ # @return [AWS::Response] The results of the request
124
+ #
125
+ # @raise [AWS::UnsuccessfulResponse, AWS::UnknownErrorResponse] on response errors
126
+ ##
127
+ def get(path, options = {})
128
+ call :get, path, options
129
+ end
107
130
 
108
- connection = AWS::Connection.new
109
- connection.call finish_and_sign_request(request)
110
- end
131
+ ##
132
+ # Send a request using HTTP PUT
133
+ #
134
+ # @param path [String] The path of the resource at hand
135
+ # @param options [Hash] Options as defined above
136
+ #
137
+ # @return [AWS::Response] The results of the request
138
+ #
139
+ # @raise [AWS::UnsuccessfulResponse, AWS::UnknownErrorResponse] on response errors
140
+ ##
141
+ def put(path, options = {})
142
+ call :put, path, options
111
143
  end
112
144
 
145
+ ##
146
+ # Send a request using HTTP DELETE
147
+ #
148
+ # @param path [String] The path of the resource at hand
149
+ # @param options [Hash] Options as defined above
150
+ #
151
+ # @return [AWS::Response] The results of the request
152
+ #
153
+ # @raise [AWS::UnsuccessfulResponse, AWS::UnknownErrorResponse] on response errors
154
+ ##
155
+ def delete(path, options = {})
156
+ call :delete, path, options
157
+ end
158
+
159
+ ##
160
+ # Send a request using HTTP HEAD
161
+ #
162
+ # @param path [String] The path of the resource at hand
163
+ # @param options [Hash] Options as defined above
164
+ #
165
+ # @return [AWS::Response] The results of the request
166
+ #
167
+ # @raise [AWS::UnsuccessfulResponse, AWS::UnknownErrorResponse] on response errors
168
+ ##
169
+ def head(path, options = {})
170
+ call :head, path, options
171
+ end
172
+
173
+ ##
174
+ # Execute an HTTP request against S3.
175
+ #
176
+ # @param method [Symbol, String] The HTTP method to use
177
+ # @param path [String] The path of the resource at hand
178
+ # @param options [Hash] Options as defined above
179
+ #
180
+ # @return [AWS::Response] The results of the request
181
+ #
182
+ # @raise [AWS::UnsuccessfulResponse, AWS::UnknownErrorResponse] on response errors
183
+ ##
184
+ def call(method, path, options = {})
185
+ request = self.build_request method, path, options
186
+
187
+ connection = AWS::Connection.new
188
+ connection.call finish_and_sign_request(request)
189
+ end
190
+
191
+ ##
192
+ # Build a request but do not send it. Helpful for debugging.
193
+ #
194
+ # @param method [Symbol, String] The HTTP method to use
195
+ # @param path [String] The path of the resource at hand
196
+ # @param options [Hash] Options as defined above
197
+ #
198
+ # @return [AWS::Request] Completed but not yet signed request object
199
+ ##
113
200
  def build_request(method, path, options = {})
114
201
  if options[:bucket]
115
- path = path.gsub(/^\//, "/#{options[:bucket]}/")
202
+ path = "/#{options[:bucket]}/#{path}".gsub("//", "/")
116
203
  end
117
204
 
118
205
  request = AWS::Request.new method, self.uri, path
@@ -156,9 +243,6 @@ module AWS
156
243
  request
157
244
  end
158
245
 
159
- ##
160
- # S3 handles region endpoints a little differently
161
- ##
162
246
  def uri
163
247
  return @uri if @uri
164
248
 
data/samples/s3.rb CHANGED
@@ -45,15 +45,15 @@ puts "", "Uploading #{file_name} to #{bucket_name}:", ""
45
45
  bad_usage unless file_name
46
46
  uploaded_file_name = File.basename file_name
47
47
 
48
- p s3.put("/#{uploaded_file_name}", :bucket => bucket_name, :file => File.open(file_name))
48
+ p s3.put(uploaded_file_name, :bucket => bucket_name, :file => File.open(file_name))
49
49
 
50
50
  puts "", "Checking that the file now exists...", ""
51
51
 
52
- p s3.head("/#{uploaded_file_name}", :bucket => bucket_name)
52
+ p s3.head(uploaded_file_name, :bucket => bucket_name)
53
53
 
54
54
  puts "", "Getting file again", ""
55
55
 
56
- p s3.get("/#{uploaded_file_name}", :bucket => bucket_name,
56
+ p s3.get(uploaded_file_name, :bucket => bucket_name,
57
57
  :params => {
58
58
  "response-content-disposition" => "attachment",
59
59
  "response-content-type" => "text/ruby",
@@ -61,18 +61,18 @@ p s3.get("/#{uploaded_file_name}", :bucket => bucket_name,
61
61
 
62
62
  puts "", "Signed, expiring URL for this resource: ", ""
63
63
 
64
- puts s3.url_for("/#{uploaded_file_name}", :bucket => bucket_name,
64
+ puts s3.url_for(uploaded_file_name, :bucket => bucket_name,
65
65
  :expires => Time.now.to_i + 120,
66
66
  :params => { "response-content-disposition" => "attachment" })
67
67
 
68
68
  puts "", "Deleting the file from S3", ""
69
69
 
70
- p s3.delete("/#{uploaded_file_name}", :bucket => bucket_name)
70
+ p s3.delete(uploaded_file_name, :bucket => bucket_name)
71
71
 
72
72
  puts "", "Checking that file is no longer in S3...", ""
73
73
 
74
74
  begin
75
- p s3.head("/#{uploaded_file_name}", :bucket => bucket_name)
75
+ p s3.head(uploaded_file_name, :bucket => bucket_name)
76
76
  rescue => ex
77
77
  puts "Not found: #{ex.message}"
78
78
  end
@@ -0,0 +1,53 @@
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 [resource path] [file to save to]
13
+ #
14
+ # This script shows one way to work with batch downloading big files from S3.
15
+ # Ensure the resource path starts with the bucket in question.
16
+ ##
17
+
18
+ def bad_usage
19
+ puts ""
20
+ puts "Usage:"
21
+ puts " ruby sample/s3_batch_download.rb [bucket name] [file to use]"
22
+ exit 1
23
+ end
24
+
25
+ s3 = AWS::S3.new ENV["AWS_KEY"], ENV["AWS_SECRET"]
26
+
27
+ s3_resource = ARGV[0]
28
+ save_to = ARGV[1]
29
+ batch_size = 1_000_000
30
+
31
+
32
+ # First, get the full size of the file in question
33
+ file_size = s3.head(s3_resource).headers["content-length"].to_i
34
+
35
+ puts "File is #{file_size} bytes"
36
+ puts "Now downloading in batches of #{batch_size} bytes"
37
+
38
+ chunk_count = 0
39
+ bytes_start = 0
40
+ bytes_to = batch_size
41
+
42
+ File.open save_to, "w+" do |file|
43
+ while bytes_start < file_size
44
+ puts "Chunk #{chunk_count} : #{bytes_start} - #{bytes_to}"
45
+ file.write s3.get(s3_resource, :headers => {"Range" => "bytes=#{bytes_start}-#{bytes_to}" }).body
46
+
47
+ bytes_start = bytes_to + 1
48
+ bytes_to += batch_size
49
+ chunk_count += 1
50
+ end
51
+ end
52
+
53
+ puts "Done"
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 = "1.0.0.pre1"
3
+ s.version = "1.0.0.pre2"
4
4
  s.platform = Gem::Platform::RUBY
5
5
  s.authors = ["Jason Roelofs"]
6
6
  s.email = ["jameskilton@gmail.com"]
data/test/aws/s3_test.rb CHANGED
@@ -71,16 +71,24 @@ describe AWS::S3 do
71
71
  end
72
72
  end
73
73
 
74
- it "rebuilds the host if :bucket given" do
74
+ it "rebuilds the path if :bucket given" do
75
75
  AWS::Connection.any_instance.expects(:call).with do |request|
76
76
  request.path.must_equal "/bucket-name/"
77
- request.host.must_equal "https://s3.amazonaws.com"
78
77
  true
79
78
  end
80
79
 
81
80
  @api.get "/", :bucket => "bucket-name"
82
81
  end
83
82
 
83
+ it "auto-fixes path names if not preceeded by a /" do
84
+ AWS::Connection.any_instance.expects(:call).with do |request|
85
+ request.path.must_equal "/bucket-name/object_name/that_thing.jpg"
86
+ true
87
+ end
88
+
89
+ @api.get "object_name/that_thing.jpg", :bucket => "bucket-name"
90
+ end
91
+
84
92
  it "takes parameters" do
85
93
  AWS::Connection.any_instance.expects(:call).with do |request|
86
94
  request.params["Parameter1"].must_equal "Value2"
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: 1.0.0.pre1
4
+ version: 1.0.0.pre2
5
5
  prerelease: 6
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-20 00:00:00.000000000 Z
12
+ date: 2012-01-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
16
- requirement: &70160933707720 !ruby/object:Gem::Requirement
16
+ requirement: &70269561987000 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 1.5.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70160933707720
24
+ version_requirements: *70269561987000
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: httparty
27
- requirement: &70160933701880 !ruby/object:Gem::Requirement
27
+ requirement: &70269561981040 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: 0.8.0
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70160933701880
35
+ version_requirements: *70269561981040
36
36
  description: SimpleAWS is a clean, simple, and forward compatible library for talking
37
37
  to Amazon's AWS APIs.
38
38
  email:
@@ -77,6 +77,7 @@ files:
77
77
  - samples/elb.rb
78
78
  - samples/iam.rb
79
79
  - samples/s3.rb
80
+ - samples/s3_batch_download.rb
80
81
  - samples/sqs.rb
81
82
  - samples/turk.rb
82
83
  - simple_aws.gemspec