awsraw 0.1.1 → 0.1.2
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 +5 -1
- data/awsraw.gemspec +2 -2
- data/lib/awsraw/s3/client.rb +6 -28
- data/lib/awsraw/s3/http_request_builder.rb +49 -0
- data/lib/awsraw/s3/md5_digester.rb +19 -0
- data/lib/awsraw/s3/request.rb +1 -1
- data/lib/awsraw/version.rb +1 -1
- data/spec/s3/client_spec.rb +3 -4
- data/spec/s3/http_request_builder_spec.rb +45 -0
- data/spec/s3/md5_digester_spec.rb +21 -0
- metadata +10 -8
data/README.md
CHANGED
@@ -31,11 +31,15 @@ s3 = AWSRaw::S3::Client.new(
|
|
31
31
|
ENV['AWS_ACCESS_KEY_ID'],
|
32
32
|
ENV['AWS_SECRET_ACCESS_KEY'])
|
33
33
|
|
34
|
+
file = File.open("reaction.gif", "rb")
|
35
|
+
|
34
36
|
s3.request(:method => "PUT",
|
35
37
|
:bucket => "mah-sekret-buckit",
|
36
38
|
:key => "reaction.gif",
|
37
|
-
:content =>
|
39
|
+
:content => file,
|
38
40
|
:headers => { "Content-Type" => "image/gif" })
|
41
|
+
|
42
|
+
f.close
|
39
43
|
```
|
40
44
|
|
41
45
|
Signed query-string requests, to allow authorized clients to get protected
|
data/awsraw.gemspec
CHANGED
@@ -5,8 +5,8 @@ require "awsraw/version"
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = "awsraw"
|
7
7
|
s.version = Awsraw::VERSION
|
8
|
-
s.authors = ["Pete Yandell", "David Goodlad"]
|
9
|
-
s.email = ["pete@notahat.com", "david@goodlad.net"]
|
8
|
+
s.authors = ["Pete Yandell", "David Goodlad", "Jack 'chendo' Chen"]
|
9
|
+
s.email = ["pete@notahat.com", "david@goodlad.net", "gems.awsraw@chen.do"]
|
10
10
|
s.license = 'MIT'
|
11
11
|
s.homepage = "http://github.com/envato/awsraw"
|
12
12
|
s.summary = %q{Minimal AWS client}
|
data/lib/awsraw/s3/client.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
require 'net/http'
|
2
2
|
require 'awsraw/s3/request'
|
3
|
+
require 'awsraw/s3/http_request_builder'
|
3
4
|
require 'awsraw/s3/response'
|
4
5
|
require 'awsraw/s3/signer'
|
5
|
-
|
6
|
+
require 'awsraw/s3/md5_digester'
|
6
7
|
module AWSRaw
|
7
8
|
module S3
|
8
9
|
|
10
|
+
class ConnectionError < StandardError; end
|
11
|
+
|
9
12
|
# A client for the AWS S3 rest API.
|
10
13
|
#
|
11
14
|
# http://docs.amazonwebservices.com/AmazonS3/latest/API/APIRest.html
|
@@ -19,7 +22,7 @@ module AWSRaw
|
|
19
22
|
def request(params = {})
|
20
23
|
request = Request.new(params, signer)
|
21
24
|
|
22
|
-
http_request =
|
25
|
+
http_request = HTTPRequestBuilder.new(request).build
|
23
26
|
|
24
27
|
http_response = Net::HTTP.start(request.uri.host, request.uri.port) do |http|
|
25
28
|
http.request(http_request)
|
@@ -30,36 +33,11 @@ module AWSRaw
|
|
30
33
|
|
31
34
|
def request!(params = {})
|
32
35
|
response = request(params)
|
33
|
-
raise
|
36
|
+
raise ConnectionError, response.inspect if response.failure?
|
34
37
|
end
|
35
38
|
|
36
39
|
private
|
37
40
|
|
38
|
-
def construct_http_request(request)
|
39
|
-
klass = http_request_class(request)
|
40
|
-
path = request.uri.request_uri
|
41
|
-
|
42
|
-
klass.new(path).tap do |http_request|
|
43
|
-
request.headers.each do |name, value|
|
44
|
-
http_request[name] = value
|
45
|
-
end
|
46
|
-
http_request.body = request.content
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def http_request_class(request)
|
51
|
-
case request.method
|
52
|
-
when "GET"
|
53
|
-
Net::HTTP::Get
|
54
|
-
when "HEAD"
|
55
|
-
Net::HTTP::Head
|
56
|
-
when "PUT"
|
57
|
-
Net::HTTP::Put
|
58
|
-
else
|
59
|
-
raise "Invalid HTTP method!"
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
41
|
def construct_response(http_response)
|
64
42
|
Response.new(
|
65
43
|
:code => http_response.code,
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
module AWSRaw
|
3
|
+
module S3
|
4
|
+
class HTTPRequestBuilder
|
5
|
+
attr_reader :s3_request
|
6
|
+
|
7
|
+
def initialize(s3_request)
|
8
|
+
@s3_request = s3_request
|
9
|
+
end
|
10
|
+
|
11
|
+
def build
|
12
|
+
klass = http_request_class(s3_request)
|
13
|
+
path = s3_request.uri.request_uri
|
14
|
+
|
15
|
+
klass.new(path).tap do |http_request|
|
16
|
+
s3_request.headers.each do |name, value|
|
17
|
+
http_request[name] = value
|
18
|
+
end
|
19
|
+
set_content_on_request(http_request, s3_request.content)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def http_request_class(s3_request)
|
26
|
+
case s3_request.method
|
27
|
+
when "GET"
|
28
|
+
Net::HTTP::Get
|
29
|
+
when "HEAD"
|
30
|
+
Net::HTTP::Head
|
31
|
+
when "PUT"
|
32
|
+
Net::HTTP::Put
|
33
|
+
else
|
34
|
+
raise "Invalid HTTP method!"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def set_content_on_request(http_request, content)
|
39
|
+
if content.is_a?(File)
|
40
|
+
http_request.body_stream = content
|
41
|
+
http_request['Content-Length'] = content.size.to_s
|
42
|
+
else
|
43
|
+
http_request.body = content
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module AWSRaw
|
2
|
+
module S3
|
3
|
+
class MD5Digester
|
4
|
+
def initialize(string_or_file)
|
5
|
+
@string_or_file = string_or_file
|
6
|
+
end
|
7
|
+
|
8
|
+
def digest
|
9
|
+
if @string_or_file.is_a?(File)
|
10
|
+
Digest::MD5.file(@string_or_file.path).digest
|
11
|
+
elsif @string_or_file.is_a?(String)
|
12
|
+
Digest::MD5.digest(@string_or_file)
|
13
|
+
else
|
14
|
+
raise "Unable to digest #{@string_or_file.class}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/awsraw/s3/request.rb
CHANGED
data/lib/awsraw/version.rb
CHANGED
data/spec/s3/client_spec.rb
CHANGED
@@ -4,14 +4,14 @@ describe AWSRaw::S3::Client do
|
|
4
4
|
|
5
5
|
subject { AWSRaw::S3::Client.new("dummy_access_key_id", "dummy_secret_access_key") }
|
6
6
|
|
7
|
-
|
7
|
+
describe "#request!" do
|
8
8
|
it "returns if the response indicates success" do
|
9
9
|
response = stub(:failure? => false)
|
10
10
|
subject.stub(:request => response)
|
11
11
|
|
12
12
|
expect {
|
13
13
|
subject.request!(:method => "PUT")
|
14
|
-
}.
|
14
|
+
}.to_not raise_error
|
15
15
|
end
|
16
16
|
|
17
17
|
it "raises an error if the response indicates failure" do
|
@@ -20,9 +20,8 @@ describe AWSRaw::S3::Client do
|
|
20
20
|
|
21
21
|
expect {
|
22
22
|
subject.request!(:method => "PUT")
|
23
|
-
}.
|
23
|
+
}.to raise_error(::AWSRaw::S3::ConnectionError)
|
24
24
|
end
|
25
25
|
end
|
26
|
-
|
27
26
|
end
|
28
27
|
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'awsraw/s3/http_request_builder'
|
2
|
+
|
3
|
+
describe AWSRaw::S3::HTTPRequestBuilder do
|
4
|
+
subject do
|
5
|
+
AWSRaw::S3::HTTPRequestBuilder.new(s3_request)
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:content) { "hello world" }
|
9
|
+
let(:s3_request) do
|
10
|
+
stub(
|
11
|
+
:uri => URI.parse("http://foo.com/foo"),
|
12
|
+
:headers => {"Content-Type" => "application/not-real"},
|
13
|
+
:content => content,
|
14
|
+
:method => "PUT"
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
context "content is a string" do
|
19
|
+
let(:content) { "hello world" }
|
20
|
+
it "sets the body on the http request to content" do
|
21
|
+
subject.build.body.should == content
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "content is a file object" do
|
26
|
+
let(:content) { File.open(__FILE__, "rb") }
|
27
|
+
it "sets the body on the http request to content" do
|
28
|
+
http_request = subject.build
|
29
|
+
http_request.body_stream.should == content
|
30
|
+
http_request['Content-Length'].should == File.size(__FILE__).to_s
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it "sets the path on the request" do
|
35
|
+
subject.build.path.should == "/foo"
|
36
|
+
end
|
37
|
+
|
38
|
+
it "sets the headers" do
|
39
|
+
subject.build["Content-Type"].should == "application/not-real"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "returns the appropriate request class" do
|
43
|
+
subject.build.class.should == Net::HTTP::Put
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'awsraw/s3/md5_digester'
|
3
|
+
|
4
|
+
describe AWSRaw::S3::MD5Digester do
|
5
|
+
|
6
|
+
describe "#digest" do
|
7
|
+
it "returns the md5 digest of the string" do
|
8
|
+
AWSRaw::S3::MD5Digester.new("hello").digest.should == Digest::MD5.digest("hello")
|
9
|
+
end
|
10
|
+
|
11
|
+
it "returns the md5 digest of a file" do
|
12
|
+
file = File.open(__FILE__, "rb")
|
13
|
+
AWSRaw::S3::MD5Digester.new(file).digest.should == Digest::MD5.file(__FILE__).digest
|
14
|
+
end
|
15
|
+
|
16
|
+
it "raises an error on unknown input" do
|
17
|
+
expect { AWSRaw::S3::MD5Digester.new(3).digest }.to raise_error("Unable to digest Fixnum")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
metadata
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: awsraw
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Pete Yandell
|
9
9
|
- David Goodlad
|
10
|
+
- Jack 'chendo' Chen
|
10
11
|
autorequire:
|
11
12
|
bindir: bin
|
12
13
|
cert_chain: []
|
13
|
-
date:
|
14
|
+
date: 2013-02-08 00:00:00.000000000 Z
|
14
15
|
dependencies:
|
15
16
|
- !ruby/object:Gem::Dependency
|
16
17
|
name: rake
|
@@ -48,6 +49,7 @@ description: A client for Amazon Web Services in the style of FlickRaw
|
|
48
49
|
email:
|
49
50
|
- pete@notahat.com
|
50
51
|
- david@goodlad.net
|
52
|
+
- gems.awsraw@chen.do
|
51
53
|
executables: []
|
52
54
|
extensions: []
|
53
55
|
extra_rdoc_files: []
|
@@ -60,12 +62,16 @@ files:
|
|
60
62
|
- awsraw.gemspec
|
61
63
|
- lib/awsraw.rb
|
62
64
|
- lib/awsraw/s3/client.rb
|
65
|
+
- lib/awsraw/s3/http_request_builder.rb
|
66
|
+
- lib/awsraw/s3/md5_digester.rb
|
63
67
|
- lib/awsraw/s3/query_string_signer.rb
|
64
68
|
- lib/awsraw/s3/request.rb
|
65
69
|
- lib/awsraw/s3/response.rb
|
66
70
|
- lib/awsraw/s3/signer.rb
|
67
71
|
- lib/awsraw/version.rb
|
68
72
|
- spec/s3/client_spec.rb
|
73
|
+
- spec/s3/http_request_builder_spec.rb
|
74
|
+
- spec/s3/md5_digester_spec.rb
|
69
75
|
- spec/s3/query_string_signer_spec.rb
|
70
76
|
- spec/s3/signer_spec.rb
|
71
77
|
homepage: http://github.com/envato/awsraw
|
@@ -81,18 +87,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
81
87
|
- - ! '>='
|
82
88
|
- !ruby/object:Gem::Version
|
83
89
|
version: '0'
|
84
|
-
segments:
|
85
|
-
- 0
|
86
|
-
hash: -2315837560340304412
|
87
90
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
91
|
none: false
|
89
92
|
requirements:
|
90
93
|
- - ! '>='
|
91
94
|
- !ruby/object:Gem::Version
|
92
95
|
version: '0'
|
93
|
-
segments:
|
94
|
-
- 0
|
95
|
-
hash: -2315837560340304412
|
96
96
|
requirements: []
|
97
97
|
rubyforge_project: awsraw
|
98
98
|
rubygems_version: 1.8.23
|
@@ -101,5 +101,7 @@ specification_version: 3
|
|
101
101
|
summary: Minimal AWS client
|
102
102
|
test_files:
|
103
103
|
- spec/s3/client_spec.rb
|
104
|
+
- spec/s3/http_request_builder_spec.rb
|
105
|
+
- spec/s3/md5_digester_spec.rb
|
104
106
|
- spec/s3/query_string_signer_spec.rb
|
105
107
|
- spec/s3/signer_spec.rb
|