jeff 0.2.4 → 0.2.5
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/.gitignore +1 -0
- data/Guardfile +1 -0
- data/README.md +6 -18
- data/examples/amazon.yml.example +3 -0
- data/examples/debug.rb +41 -0
- data/jeff.gemspec +1 -2
- data/lib/jeff.rb +39 -28
- data/lib/jeff/secret.rb +21 -0
- data/lib/jeff/version.rb +1 -1
- data/spec/jeff/secret_spec.rb +20 -0
- data/spec/jeff_spec.rb +4 -0
- data/spec/spec_helper.rb +9 -1
- metadata +10 -26
data/.gitignore
CHANGED
data/Guardfile
CHANGED
data/README.md
CHANGED
@@ -76,32 +76,20 @@ Requests can be instrumented.
|
|
76
76
|
```ruby
|
77
77
|
class Logger
|
78
78
|
def self.instrument(name, params = {})
|
79
|
-
|
80
|
-
|
81
|
-
params[:scheme],
|
82
|
-
'://',
|
83
|
-
params[:host],
|
84
|
-
'/',
|
85
|
-
params[:path],
|
86
|
-
'?',
|
87
|
-
params[:query]
|
88
|
-
].join
|
89
|
-
yield if block_given?
|
90
|
-
end
|
79
|
+
$stderr.puts name, params
|
80
|
+
yield if block_given?
|
91
81
|
end
|
92
82
|
end
|
93
83
|
|
94
|
-
client.get query:
|
95
|
-
instrumentor: Logger
|
84
|
+
client.get query: {}, instrumentor: Logger
|
96
85
|
```
|
97
86
|
|
98
87
|
### Miscellaneous
|
99
88
|
|
100
|
-
HTTP connections are persistent.
|
89
|
+
* HTTP connections are persistent.
|
90
|
+
* By default, Jeff will retry failed requests 4 times.
|
101
91
|
|
102
|
-
|
103
|
-
|
104
|
-
For more detailed configuration options, check out [excon][excon].
|
92
|
+
For more detailed configuration options, read [excon][excon].
|
105
93
|
|
106
94
|
## Compatibility
|
107
95
|
|
data/examples/debug.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
$:.unshift File.expand_path '../../lib', __FILE__
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
require 'jeff'
|
6
|
+
require 'pry'
|
7
|
+
require 'pry-doc'
|
8
|
+
|
9
|
+
class Client
|
10
|
+
include Jeff
|
11
|
+
|
12
|
+
params 'AssociateTag' => -> { tag },
|
13
|
+
'Service' => 'AWSECommerceService',
|
14
|
+
'Version' => '2011-08-01'
|
15
|
+
|
16
|
+
attr_accessor :tag
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
self.key = config['key']
|
20
|
+
self.secret = config['secret']
|
21
|
+
self.tag = config['tag']
|
22
|
+
self.endpoint = 'http://ecs.amazonaws.com/onca/xml'
|
23
|
+
end
|
24
|
+
|
25
|
+
def find(asins)
|
26
|
+
params = {
|
27
|
+
'Operation' => 'ItemLookup',
|
28
|
+
'ItemId' => Array(asins).join(',')
|
29
|
+
}
|
30
|
+
|
31
|
+
get query: params
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def config
|
37
|
+
@config ||= YAML.load_file File.expand_path '../amazon.yml', __FILE__
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
binding.pry
|
data/jeff.gemspec
CHANGED
@@ -16,9 +16,8 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.require_paths = ['lib']
|
17
17
|
gem.version = Jeff::VERSION
|
18
18
|
|
19
|
-
gem.add_dependency 'excon', '~> 0.14.
|
19
|
+
gem.add_dependency 'excon', '~> 0.14.3'
|
20
20
|
gem.add_development_dependency 'guard-rspec'
|
21
|
-
gem.add_development_dependency 'pry'
|
22
21
|
gem.add_development_dependency 'rake'
|
23
22
|
gem.add_development_dependency 'rspec'
|
24
23
|
end
|
data/lib/jeff.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
require 'base64'
|
2
1
|
require 'time'
|
3
2
|
|
4
3
|
require 'excon'
|
5
4
|
|
5
|
+
require 'jeff/secret'
|
6
6
|
require 'jeff/version'
|
7
7
|
|
8
8
|
module Jeff
|
@@ -10,32 +10,44 @@ module Jeff
|
|
10
10
|
MissingKey = Class.new ArgumentError
|
11
11
|
MissingSecret = Class.new ArgumentError
|
12
12
|
|
13
|
-
SHA256 = OpenSSL::Digest::SHA256.new
|
14
13
|
UNRESERVED = /([^\w.~-]+)/
|
15
14
|
|
16
15
|
def self.included(base)
|
17
16
|
base.extend ClassMethods
|
18
17
|
end
|
19
18
|
|
20
|
-
#
|
19
|
+
# Internal: Builds a sorted query.
|
20
|
+
#
|
21
|
+
# hsh - A hash of query parameters specific to the request.
|
22
|
+
#
|
23
|
+
# Returns a query String.
|
24
|
+
def build_query(hsh)
|
25
|
+
default_params
|
26
|
+
.merge(hsh)
|
27
|
+
.map { |k, v| "#{k}=#{ escape v }" }
|
28
|
+
.sort
|
29
|
+
.join '&'
|
30
|
+
end
|
31
|
+
|
32
|
+
# Internal: Returns an Excon::Connection.
|
21
33
|
def connection
|
22
34
|
@connection ||= Excon.new endpoint, headers: default_headers,
|
23
35
|
idempotent: true
|
24
36
|
end
|
25
37
|
|
26
|
-
# Returns the Hash default request parameters.
|
38
|
+
# Internal: Returns the Hash default request parameters.
|
27
39
|
def default_params
|
28
40
|
self.class.params.reduce({}) do |a, (k, v)|
|
29
41
|
a.update k => (v.is_a?(Proc) ? instance_exec(&v) : v)
|
30
42
|
end
|
31
43
|
end
|
32
44
|
|
33
|
-
# Returns the Hash default headers.
|
45
|
+
# Internal: Returns the Hash default headers.
|
34
46
|
def default_headers
|
35
47
|
self.class.headers
|
36
48
|
end
|
37
49
|
|
38
|
-
# Gets the String AWS endpoint.
|
50
|
+
# Internal: Gets the String AWS endpoint.
|
39
51
|
#
|
40
52
|
# Raises a MissingEndpoint error if endpoint is missing.
|
41
53
|
def endpoint
|
@@ -45,7 +57,7 @@ module Jeff
|
|
45
57
|
# Sets the String AWS endpoint.
|
46
58
|
attr_writer :endpoint
|
47
59
|
|
48
|
-
# Gets the String AWS access key id.
|
60
|
+
# Internal: Gets the String AWS access key id.
|
49
61
|
#
|
50
62
|
# Raises a MissingKey error if key is missing.
|
51
63
|
def key
|
@@ -55,15 +67,21 @@ module Jeff
|
|
55
67
|
# Sets the String AWS access key id.
|
56
68
|
attr_writer :key
|
57
69
|
|
58
|
-
# Gets the
|
70
|
+
# Internal: Gets the Jeff::Secret.
|
59
71
|
#
|
60
72
|
# Raises a MissingSecret error if secret is missing.
|
61
73
|
def secret
|
62
74
|
@secret or raise MissingSecret
|
63
75
|
end
|
64
76
|
|
65
|
-
# Sets the
|
66
|
-
|
77
|
+
# Sets the AWS secret key.
|
78
|
+
#
|
79
|
+
# key - A String secret.
|
80
|
+
#
|
81
|
+
# Returns a Jeff::Secret.
|
82
|
+
def secret=(key)
|
83
|
+
@secret = Secret.new key
|
84
|
+
end
|
67
85
|
|
68
86
|
# Generate HTTP request verb methods that sign queries and then delegate
|
69
87
|
# request to Excon.
|
@@ -76,19 +94,6 @@ module Jeff
|
|
76
94
|
DEF
|
77
95
|
end
|
78
96
|
|
79
|
-
# Internal: Builds a sorted query.
|
80
|
-
#
|
81
|
-
# hsh - A hash of query parameters specific to the request.
|
82
|
-
#
|
83
|
-
# Returns a query String.
|
84
|
-
def build_query(hsh)
|
85
|
-
default_params
|
86
|
-
.merge(hsh)
|
87
|
-
.map { |k, v| "#{k}=#{ escape v }" }
|
88
|
-
.sort
|
89
|
-
.join '&'
|
90
|
-
end
|
91
|
-
|
92
97
|
private
|
93
98
|
|
94
99
|
def sign(opts)
|
@@ -96,13 +101,11 @@ module Jeff
|
|
96
101
|
|
97
102
|
string_to_sign = [
|
98
103
|
opts[:method].upcase,
|
99
|
-
|
100
|
-
opts[:path] ||
|
104
|
+
connection_host,
|
105
|
+
opts[:path] || connection_path,
|
101
106
|
query
|
102
107
|
].join "\n"
|
103
|
-
|
104
|
-
digest = OpenSSL::HMAC.digest SHA256, secret, string_to_sign
|
105
|
-
signature = Base64.encode64(digest).chomp
|
108
|
+
signature = secret.sign string_to_sign
|
106
109
|
|
107
110
|
opts.update query: [
|
108
111
|
query,
|
@@ -110,6 +113,14 @@ module Jeff
|
|
110
113
|
].join('&')
|
111
114
|
end
|
112
115
|
|
116
|
+
def connection_host
|
117
|
+
[connection.connection[:host], connection.connection[:port]].join ':'
|
118
|
+
end
|
119
|
+
|
120
|
+
def connection_path
|
121
|
+
connection.connection[:path]
|
122
|
+
end
|
123
|
+
|
113
124
|
def escape(val)
|
114
125
|
val.to_s.gsub(UNRESERVED) do
|
115
126
|
'%' + $1.unpack('H2' * $1.bytesize).join('%').upcase
|
data/lib/jeff/secret.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
3
|
+
module Jeff
|
4
|
+
class Secret
|
5
|
+
SHA256 = OpenSSL::Digest::SHA256.new
|
6
|
+
|
7
|
+
def initialize(key)
|
8
|
+
@key = key
|
9
|
+
end
|
10
|
+
|
11
|
+
def sign(message)
|
12
|
+
Base64.encode64(digest(message)).chomp
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def digest(message)
|
18
|
+
OpenSSL::HMAC.digest SHA256, @key, message
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/jeff/version.rb
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Jeff
|
4
|
+
describe Secret do
|
5
|
+
let(:secret) { Secret.new 'key' }
|
6
|
+
|
7
|
+
describe '#sign' do
|
8
|
+
after { secret.sign 'message' }
|
9
|
+
|
10
|
+
it 'should digest' do
|
11
|
+
secret.should_receive(:digest)
|
12
|
+
.and_return double.as_null_object
|
13
|
+
end
|
14
|
+
it 'should Base64-encode' do
|
15
|
+
Base64.should_receive(:encode64)
|
16
|
+
.and_return double.as_null_object
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/spec/jeff_spec.rb
CHANGED
@@ -128,6 +128,8 @@ describe Jeff do
|
|
128
128
|
end
|
129
129
|
end
|
130
130
|
|
131
|
+
after { Excon.stubs.clear }
|
132
|
+
|
131
133
|
it "should make a #{method.upcase} request" do
|
132
134
|
subject[:method].should eql method.to_sym
|
133
135
|
end
|
@@ -151,6 +153,8 @@ describe Jeff do
|
|
151
153
|
end
|
152
154
|
end
|
153
155
|
|
156
|
+
after { Excon.stubs.clear }
|
157
|
+
|
154
158
|
it 'should retry' do
|
155
159
|
client.get(mock: true).status.should be 200
|
156
160
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jeff
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
12
|
+
date: 2012-07-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: excon
|
@@ -18,7 +18,7 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 0.14.
|
21
|
+
version: 0.14.3
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 0.14.
|
29
|
+
version: 0.14.3
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: guard-rspec
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -43,22 +43,6 @@ dependencies:
|
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
|
-
- !ruby/object:Gem::Dependency
|
47
|
-
name: pry
|
48
|
-
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
|
-
requirements:
|
51
|
-
- - ! '>='
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '0'
|
54
|
-
type: :development
|
55
|
-
prerelease: false
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
|
-
requirements:
|
59
|
-
- - ! '>='
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
46
|
- !ruby/object:Gem::Dependency
|
63
47
|
name: rake
|
64
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -105,9 +89,13 @@ files:
|
|
105
89
|
- LICENSE
|
106
90
|
- README.md
|
107
91
|
- Rakefile
|
92
|
+
- examples/amazon.yml.example
|
93
|
+
- examples/debug.rb
|
108
94
|
- jeff.gemspec
|
109
95
|
- lib/jeff.rb
|
96
|
+
- lib/jeff/secret.rb
|
110
97
|
- lib/jeff/version.rb
|
98
|
+
- spec/jeff/secret_spec.rb
|
111
99
|
- spec/jeff_spec.rb
|
112
100
|
- spec/spec_helper.rb
|
113
101
|
homepage: https://github.com/hakanensari/jeff
|
@@ -122,18 +110,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
122
110
|
- - ! '>='
|
123
111
|
- !ruby/object:Gem::Version
|
124
112
|
version: '0'
|
125
|
-
segments:
|
126
|
-
- 0
|
127
|
-
hash: 13761434509478082
|
128
113
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
129
114
|
none: false
|
130
115
|
requirements:
|
131
116
|
- - ! '>='
|
132
117
|
- !ruby/object:Gem::Version
|
133
118
|
version: '0'
|
134
|
-
segments:
|
135
|
-
- 0
|
136
|
-
hash: 13761434509478082
|
137
119
|
requirements: []
|
138
120
|
rubyforge_project:
|
139
121
|
rubygems_version: 1.8.23
|
@@ -141,5 +123,7 @@ signing_key:
|
|
141
123
|
specification_version: 3
|
142
124
|
summary: AWS client
|
143
125
|
test_files:
|
126
|
+
- spec/jeff/secret_spec.rb
|
144
127
|
- spec/jeff_spec.rb
|
145
128
|
- spec/spec_helper.rb
|
129
|
+
has_rdoc:
|