jeff 1.0.1 → 1.1.0
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +2 -1
- data/Gemfile +4 -2
- data/README.md +2 -8
- data/Rakefile +5 -6
- data/jeff.gemspec +11 -11
- data/lib/jeff.rb +36 -23
- data/lib/jeff/version.rb +1 -1
- data/test/test_jeff.rb +41 -23
- metadata +15 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2acf8a725f47146cc30fbae49e80c7b264596681
|
4
|
+
data.tar.gz: 76ae8492c0281afdbd8b5b48c213a65abe774b22
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 664387a93beb1ba57352c12fd1937952a7f6ddca07118a3ab7bc114737b69f59108c7e2603fa31a1b38cfe5573a931eb113f17c7719f25aa9d0d14cf2e325b98
|
7
|
+
data.tar.gz: 0644c4f20f9a14ef53ca6c618534569c8e88277d177c136460dbfa3352b104122d53c475c2cc9e73b4f8fe6ddb7f7b7dd5923a2da844530bf644df1a058586e5
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,14 +1,8 @@
|
|
1
1
|
# Jeff
|
2
2
|
|
3
|
-
Jeff [signs requests][signature] to some Amazon Web Services.
|
3
|
+
Jeff is a small mixin that [signs requests][signature] to some Amazon Web Services. My gems [Vacuum][vacuum] and [Peddler][peddler] build on Jeff.
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
## Usage
|
8
|
-
|
9
|
-
<img src="http://f.cl.ly/items/0q0X2f0U053F1U3h131N/jeff-2.jpg">
|
10
|
-
<img src="http://f.cl.ly/items/0I1U1p3E3r1z2V2x3l35/jeff-1.jpg">
|
11
|
-
<img src="http://f.cl.ly/items/161x3q280o0U3d3v352H/jeff-3.jpg">
|
5
|
+
<img src="http://cl.ly/XatM/jeff.gif" style="display: inline-block; max-width: 300px; margin: 1em auto;">
|
12
6
|
|
13
7
|
[signature]: http://docs.amazonwebservices.com/general/latest/gr/signature-version-2.html
|
14
8
|
[vacuum]: https://github.com/hakanensari/vacuum
|
data/Rakefile
CHANGED
@@ -1,10 +1,9 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rake/testtask"
|
3
3
|
|
4
4
|
Rake::TestTask.new do |t|
|
5
|
-
t.libs.push
|
6
|
-
t.test_files = FileList[
|
7
|
-
t.verbose = true
|
5
|
+
t.libs.push "lib"
|
6
|
+
t.test_files = FileList["test/test_*.rb"]
|
8
7
|
end
|
9
8
|
|
10
|
-
task :
|
9
|
+
task default: :test
|
data/jeff.gemspec
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
$:.push File.expand_path(
|
3
|
-
require File.expand_path(
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require File.expand_path("../lib/jeff/version.rb", __FILE__)
|
4
4
|
|
5
5
|
Gem::Specification.new do |gem|
|
6
|
-
gem.authors = [
|
7
|
-
gem.email = [
|
6
|
+
gem.authors = ["Hakan Ensari"]
|
7
|
+
gem.email = ["me@hakanensari.com"]
|
8
8
|
gem.description = %q{An Amazon Web Services client}
|
9
9
|
gem.summary = %q{An AWS client}
|
10
|
-
gem.homepage =
|
10
|
+
gem.homepage = "https://github.com/hakanensari/jeff"
|
11
11
|
|
12
12
|
gem.files = `git ls-files`.split($\)
|
13
13
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
-
gem.name =
|
15
|
-
gem.require_paths = [
|
14
|
+
gem.name = "jeff"
|
15
|
+
gem.require_paths = ["lib"]
|
16
16
|
gem.version = Jeff::VERSION
|
17
17
|
|
18
|
-
gem.add_dependency
|
19
|
-
gem.add_development_dependency
|
20
|
-
gem.add_development_dependency
|
18
|
+
gem.add_dependency "excon", ">= 0.22.1"
|
19
|
+
gem.add_development_dependency "minitest"
|
20
|
+
gem.add_development_dependency "rake"
|
21
21
|
|
22
|
-
gem.required_ruby_version =
|
22
|
+
gem.required_ruby_version = ">= 1.9"
|
23
23
|
end
|
data/lib/jeff.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
# Jeff
|
2
|
-
require
|
1
|
+
# Jeff"s only external dependency.
|
2
|
+
require "excon"
|
3
3
|
|
4
4
|
# Standard library dependencies.
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
5
|
+
require "base64"
|
6
|
+
require "openssl"
|
7
|
+
require "time"
|
8
8
|
|
9
|
-
require
|
9
|
+
require "jeff/version"
|
10
10
|
|
11
11
|
# Jeff mixes in client behaviour for Amazon Web Services (AWS) that require
|
12
12
|
# Signature version 2 authentication.
|
@@ -20,7 +20,7 @@ module Jeff
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def to_s
|
23
|
-
values.sort.map { |k, v| "#{k}=#{ Utils.escape(v) }" }.join(
|
23
|
+
values.sort.map { |k, v| "#{k}=#{ Utils.escape(v) }" }.join("&")
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -70,26 +70,21 @@ module Jeff
|
|
70
70
|
end
|
71
71
|
|
72
72
|
def secret
|
73
|
-
@secret or raise ArgumentError.new(
|
73
|
+
@secret or raise ArgumentError.new("Missing secret")
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
-
# Because Ruby
|
77
|
+
# Because Ruby"s CGI escapes tilde, use a custom escape.
|
78
78
|
module Utils
|
79
79
|
UNRESERVED = /([^\w.~-]+)/
|
80
80
|
|
81
81
|
def self.escape(val)
|
82
82
|
val.to_s.gsub(UNRESERVED) do
|
83
|
-
|
83
|
+
"%" + $1.unpack("H2" * $1.bytesize).join("%").upcase
|
84
84
|
end
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
-
# Amazon recommends to include a User-Agent header with every request to
|
89
|
-
# identify the application, its version number, programming language, and
|
90
|
-
# host.
|
91
|
-
USER_AGENT = "Jeff/#{VERSION} (Language=Ruby; #{`hostname`.chomp})"
|
92
|
-
|
93
88
|
def self.included(base)
|
94
89
|
base.extend(ClassMethods)
|
95
90
|
|
@@ -98,17 +93,17 @@ module Jeff
|
|
98
93
|
# Add other common parameters using `Jeff.params` if required in your
|
99
94
|
# implementation.
|
100
95
|
base.params(
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
96
|
+
"AWSAccessKeyId" => -> { aws_access_key_id },
|
97
|
+
"SignatureVersion" => "2",
|
98
|
+
"SignatureMethod" => "HmacSHA256",
|
99
|
+
"Timestamp" => -> { Time.now.utc.iso8601 }
|
105
100
|
)
|
106
101
|
end
|
107
102
|
|
108
103
|
# A reusable HTTP connection.
|
109
104
|
def connection
|
110
105
|
@connection ||= Excon.new(aws_endpoint,
|
111
|
-
headers: {
|
106
|
+
headers: { "User-Agent" => self.class.user_agent },
|
112
107
|
expects: 200,
|
113
108
|
omit_default_port: true
|
114
109
|
)
|
@@ -119,11 +114,11 @@ module Jeff
|
|
119
114
|
attr_writer :aws_access_key_id, :aws_secret_access_key
|
120
115
|
|
121
116
|
def aws_access_key_id
|
122
|
-
@aws_access_key_id || ENV[
|
117
|
+
@aws_access_key_id || ENV["AWS_ACCESS_KEY_ID"]
|
123
118
|
end
|
124
119
|
|
125
120
|
def aws_secret_access_key
|
126
|
-
@aws_secret_access_key || ENV[
|
121
|
+
@aws_secret_access_key || ENV["AWS_SECRET_ACCESS_KEY"]
|
127
122
|
end
|
128
123
|
|
129
124
|
# Generate HTTP request verb methods.
|
@@ -142,7 +137,7 @@ module Jeff
|
|
142
137
|
# Add Content-MD5 header if uploading a file.
|
143
138
|
if options.has_key?(:body)
|
144
139
|
md5 = Content.new(options[:body]).md5
|
145
|
-
(options[:headers] ||= {}).store(
|
140
|
+
(options[:headers] ||= {}).store("Content-MD5", md5)
|
146
141
|
end
|
147
142
|
|
148
143
|
# Build query string.
|
@@ -169,5 +164,23 @@ module Jeff
|
|
169
164
|
def params(hsh = {})
|
170
165
|
(@params ||= {}).update(hsh)
|
171
166
|
end
|
167
|
+
|
168
|
+
def user_agent
|
169
|
+
@user_agent ||= default_user_agent
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
def user_agent=(user_agent)
|
174
|
+
@user_agent = user_agent
|
175
|
+
end
|
176
|
+
|
177
|
+
private
|
178
|
+
|
179
|
+
# Amazon recommends to include a User-Agent header with every request to
|
180
|
+
# identify the application, its version number, programming language, and
|
181
|
+
# host.
|
182
|
+
def default_user_agent
|
183
|
+
"Jeff/#{VERSION} (Language=Ruby; #{`hostname`.chomp})"
|
184
|
+
end
|
172
185
|
end
|
173
186
|
end
|
data/lib/jeff/version.rb
CHANGED
data/test/test_jeff.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
|
4
|
-
|
5
|
-
Excon.defaults[:mock] = true
|
1
|
+
require "minitest/autorun"
|
2
|
+
require "minitest/pride"
|
3
|
+
require_relative "../lib/jeff"
|
6
4
|
|
7
5
|
class TestJeff < Minitest::Test
|
8
6
|
def setup
|
@@ -10,7 +8,7 @@ class TestJeff < Minitest::Test
|
|
10
8
|
end
|
11
9
|
|
12
10
|
def test_delegates_unset_aws_credential_to_env_vars
|
13
|
-
key =
|
11
|
+
key = "123456"
|
14
12
|
client = @klass.new
|
15
13
|
%w(aws_access_key_id aws_secret_access_key).each do |attr|
|
16
14
|
ENV[attr.upcase] = key
|
@@ -28,48 +26,68 @@ class TestJeff < Minitest::Test
|
|
28
26
|
|
29
27
|
def test_configures_request_query_parameters
|
30
28
|
@klass.instance_eval do
|
31
|
-
params
|
29
|
+
params "Foo" => "bar"
|
32
30
|
end
|
33
|
-
assert @klass.params.has_key?(
|
31
|
+
assert @klass.params.has_key?("Foo")
|
34
32
|
end
|
35
33
|
|
36
34
|
def test_requires_signature
|
37
35
|
signature = Jeff::Signature.new(nil)
|
38
|
-
assert_raises(ArgumentError) { signature.sign(
|
36
|
+
assert_raises(ArgumentError) { signature.sign("foo") }
|
39
37
|
end
|
40
38
|
|
41
39
|
def test_sorts_request_query_parameters_lexicographically
|
42
|
-
query = Jeff::Query.new(
|
43
|
-
assert_equal
|
40
|
+
query = Jeff::Query.new("A10" => 1, "A1" => 1)
|
41
|
+
assert_equal "A1=1&A10=1", query.to_s
|
44
42
|
end
|
45
43
|
|
46
44
|
def test_sets_user_agent_header
|
47
45
|
client = @klass.new
|
48
|
-
client.aws_endpoint =
|
49
|
-
|
46
|
+
client.aws_endpoint = "http://example.com/"
|
47
|
+
assert_includes client.connection.data[:headers]["User-Agent"], "Jeff"
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_allows_customizing_user_agent
|
51
|
+
@klass.user_agent = "CustomApp/1.0"
|
52
|
+
client = @klass.new
|
53
|
+
client.aws_endpoint = "http://example.com/"
|
54
|
+
assert_equal "CustomApp/1.0", client.connection.data[:headers]["User-Agent"]
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_does_not_escape_tilde
|
58
|
+
assert_equal "~%2C", Jeff::Utils.escape("~,")
|
50
59
|
end
|
51
60
|
|
52
61
|
Excon::HTTP_VERBS.each do |method|
|
53
62
|
define_method "test_makes_#{method}_request" do
|
54
63
|
Excon.stub({ }, { status: 200 })
|
55
64
|
client = @klass.new
|
56
|
-
client.aws_endpoint =
|
57
|
-
client.aws_access_key_id =
|
58
|
-
client.aws_secret_access_key =
|
59
|
-
assert_equal 200, client.send(method).status
|
65
|
+
client.aws_endpoint = "http://example.com/"
|
66
|
+
client.aws_access_key_id = "foo"
|
67
|
+
client.aws_secret_access_key = "bar"
|
68
|
+
assert_equal 200, client.send(method, mock: true).status
|
60
69
|
Excon.stubs.clear
|
61
70
|
end
|
62
71
|
end
|
63
72
|
|
64
|
-
def
|
73
|
+
def test_adds_content_md5_request_header_if_given_a_request_body
|
65
74
|
Excon.stub({ }) do |params|
|
66
|
-
{ body: params[:headers][
|
75
|
+
{ body: params[:headers]["Content-MD5"] }
|
67
76
|
end
|
68
77
|
client = @klass.new
|
69
|
-
client.aws_endpoint =
|
70
|
-
client.aws_access_key_id =
|
71
|
-
client.aws_secret_access_key =
|
72
|
-
refute_empty client.post(body:
|
78
|
+
client.aws_endpoint = "http://example.com/"
|
79
|
+
client.aws_access_key_id = "foo"
|
80
|
+
client.aws_secret_access_key = "bar"
|
81
|
+
refute_empty client.post(body: "foo", mock: true).body
|
73
82
|
Excon.stubs.clear
|
74
83
|
end
|
84
|
+
|
85
|
+
def test_integration
|
86
|
+
client = @klass.new
|
87
|
+
client.aws_access_key_id = "foo"
|
88
|
+
client.aws_secret_access_key = "bar"
|
89
|
+
client.aws_endpoint = "https://mws.amazonservices.com/Sellers/2011-07-01"
|
90
|
+
res = client.post(query: { "Action" => "GetServiceStatus"})
|
91
|
+
assert_equal 200, res.status
|
92
|
+
end
|
75
93
|
end
|
metadata
CHANGED
@@ -1,66 +1,66 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jeff
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hakan Ensari
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-10-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: excon
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 0.22.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 0.22.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: minitest
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
description: An Amazon Web Services client
|
56
56
|
email:
|
57
|
-
-
|
57
|
+
- me@hakanensari.com
|
58
58
|
executables: []
|
59
59
|
extensions: []
|
60
60
|
extra_rdoc_files: []
|
61
61
|
files:
|
62
|
-
- .gitignore
|
63
|
-
- .travis.yml
|
62
|
+
- ".gitignore"
|
63
|
+
- ".travis.yml"
|
64
64
|
- CHANGELOG.md
|
65
65
|
- Gemfile
|
66
66
|
- LICENSE
|
@@ -70,7 +70,7 @@ files:
|
|
70
70
|
- lib/jeff.rb
|
71
71
|
- lib/jeff/version.rb
|
72
72
|
- test/test_jeff.rb
|
73
|
-
homepage: https://github.com/
|
73
|
+
homepage: https://github.com/hakanensari/jeff
|
74
74
|
licenses: []
|
75
75
|
metadata: {}
|
76
76
|
post_install_message:
|
@@ -79,20 +79,19 @@ require_paths:
|
|
79
79
|
- lib
|
80
80
|
required_ruby_version: !ruby/object:Gem::Requirement
|
81
81
|
requirements:
|
82
|
-
- -
|
82
|
+
- - ">="
|
83
83
|
- !ruby/object:Gem::Version
|
84
84
|
version: '1.9'
|
85
85
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
requirements: []
|
91
91
|
rubyforge_project:
|
92
|
-
rubygems_version: 2.
|
92
|
+
rubygems_version: 2.2.2
|
93
93
|
signing_key:
|
94
94
|
specification_version: 4
|
95
95
|
summary: An AWS client
|
96
96
|
test_files:
|
97
97
|
- test/test_jeff.rb
|
98
|
-
has_rdoc:
|