awis-sdk-ruby 0.1.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -20,8 +20,8 @@ Awis.config do |c|
20
20
  c.secret_access_key = AWIS_CONFIG['secret_access_key']
21
21
  c.debug = AWIS_CONFIG['debug']
22
22
  c.protocol = 'https' # Default 'https'
23
- c.timeout = 5 # Default 5
24
- c.open_timeout = 5 # Default 2
23
+ c.timeout = 10 # Default 10
24
+ c.open_timeout = 10 # Default 10
25
25
  c.logger = false # Default nil
26
26
  end
27
27
  ```
@@ -116,7 +116,7 @@ You can specify options:
116
116
 
117
117
  ``` ruby
118
118
  client = Awis::Client.new
119
- category_listings = client.category_listings(path: "Top/Games/Card_Games")
119
+ category_listings = client.category_listings(path: "Top/Arts")
120
120
  ```
121
121
 
122
122
  If you looking for the API request URI:
@@ -136,7 +136,7 @@ Returns object that contains relationships:
136
136
 
137
137
  ``` ruby
138
138
  client = Awis::Client.new
139
- category_browses = client.category_browse(path: "Top/Games/Card_Games")
139
+ category_browses = client.category_browse(path: "Top/Arts")
140
140
  ```
141
141
 
142
142
  If you looking for the API request URI:
@@ -154,6 +154,10 @@ Returns object that contains relationships:
154
154
 
155
155
  * listings [:data_url, :title, :popularity_rank, :description]
156
156
 
157
+ ##### How to run test
158
+
159
+ * rake test
160
+
157
161
  ##### Request ID and Status Code
158
162
 
159
163
  You can retrieve status code and requestID
@@ -23,10 +23,10 @@ Gem::Specification.new do |spec|
23
23
  spec.required_ruby_version = ">= 1.9.3"
24
24
 
25
25
  spec.add_dependency "multi_xml", ">= 0.5.0"
26
- spec.add_dependency "faraday", "~> 0.9.0"
27
26
  spec.add_dependency "nokogiri", '~> 1.6.8'
28
27
 
29
28
  spec.add_development_dependency "minitest"
30
29
  spec.add_development_dependency "mocha"
31
30
  spec.add_development_dependency "webmock"
31
+ spec.add_development_dependency "pry"
32
32
  end
File without changes
@@ -3,9 +3,7 @@ require "nokogiri"
3
3
 
4
4
  require "awis/version"
5
5
  require "awis/hash"
6
- require "awis/utils/xml"
7
- require "awis/utils/extra"
8
- require "awis/utils/variable"
6
+ require "awis/utils"
9
7
  require "awis/exceptions"
10
8
  require "awis/connection"
11
9
  require "awis/config"
@@ -14,9 +12,12 @@ require "awis/api"
14
12
  require "awis/models"
15
13
 
16
14
  module Awis
17
- API_VERSION = "2005-07-11".freeze
18
- API_HOST = "awis.amazonaws.com".freeze
19
- API_SIGNATURE_VERSION = "2".freeze
15
+ SERVICE_HOST = "awis.amazonaws.com".freeze
16
+ SERVICE_ENDPOINT = "awis.us-west-1.amazonaws.com".freeze
17
+ SERVICE_PORT = 443
18
+ SERVICE_URI = "/api".freeze
19
+ SERVICE_REGION = "us-west-1".freeze
20
+ SERVICE_NAME = "awis".freeze
20
21
 
21
22
  class << self
22
23
  end
@@ -34,7 +34,7 @@ module Awis
34
34
  def load_request_uri(params)
35
35
  collection = Awis::Connection.new
36
36
  collection.setup_params(params)
37
- collection.request_url
37
+ collection.uri
38
38
  end
39
39
 
40
40
  def before_validation_arguments(arguments)
@@ -28,15 +28,15 @@ module Awis
28
28
  def parse_response_with_request(kclass, args)
29
29
  case kclass
30
30
  when 'UrlInfo'
31
- Awis::Models::UrlInfo.new Awis::API::UrlInfo.new.fetch(args)
31
+ Models::UrlInfo.new API::UrlInfo.new.fetch(args)
32
32
  when 'SitesLinkingIn'
33
- Awis::Models::SitesLinkingIn.new Awis::API::SitesLinkingIn.new.fetch(args)
33
+ Models::SitesLinkingIn.new API::SitesLinkingIn.new.fetch(args)
34
34
  when 'TrafficHistory'
35
- Awis::Models::TrafficHistory.new Awis::API::TrafficHistory.new.fetch(args)
35
+ Models::TrafficHistory.new API::TrafficHistory.new.fetch(args)
36
36
  when 'CategoryBrowse'
37
- Awis::Models::CategoryBrowse.new Awis::API::CategoryBrowse.new.fetch(args)
37
+ Models::CategoryBrowse.new API::CategoryBrowse.new.fetch(args)
38
38
  when 'CategoryListings'
39
- Awis::Models::CategoryListings.new Awis::API::CategoryListings.new.fetch(args)
39
+ Models::CategoryListings.new API::CategoryListings.new.fetch(args)
40
40
  end
41
41
  end
42
42
  end
@@ -1,12 +1,7 @@
1
- require "cgi"
2
- require "base64"
3
- require "openssl"
4
- require "digest/sha1"
5
- require "faraday"
6
- require "time"
7
-
8
1
  module Awis
9
2
  class Connection
3
+ include Awis::Utils::Request
4
+
10
5
  attr_accessor :debug, :protocol
11
6
  attr_writer :params
12
7
 
@@ -19,8 +14,8 @@ module Awis
19
14
  def setup_options!
20
15
  @debug = Awis.config.debug || false
21
16
  @protocol = Awis.config.protocol || 'https'
22
- @timeout = Awis.config.timeout || 5
23
- @open_timeout = Awis.config.open_timeout || 2
17
+ @timeout = Awis.config.timeout || 10
18
+ @open_timeout = Awis.config.open_timeout || 10
24
19
  end
25
20
 
26
21
  def params
@@ -34,82 +29,8 @@ module Awis
34
29
  def get(params = {})
35
30
  setup_params(params)
36
31
 
37
- handle_response(request).body.force_encoding(Encoding::UTF_8)
38
- end
39
-
40
- def handle_response(response)
41
- case response.status.to_i
42
- when 200...300
43
- response
44
- when 300...600
45
- if response.body.nil?
46
- raise ResponseError.new(nil, response)
47
- else
48
- xml = MultiXml.parse(response.body)
49
- message = xml["Response"]["Errors"]["Error"]["Message"]
50
- raise ResponseError.new(message, response)
51
- end
52
- else
53
- raise ResponseError.new("Unknown code: #{respnse.code}", response)
54
- end
55
- end
56
-
57
- def request
58
- connection = Faraday.new(url: host_with_port) do |faraday|
59
- faraday.request :url_encoded # form-encode POST params
60
- faraday.response :logger do |logger|
61
- logger.filter(/(AWSAccessKeyId=)(\w+)/, '\1[REMOVED]')
62
- end if Awis.config.logger
63
- faraday.adapter :net_http
64
- end
65
-
66
- connection.get do |req|
67
- req.url url_params
68
- req.options.open_timeout = @timeout
69
- req.options.timeout = @open_timeout
70
- end
71
- end
72
-
73
- def host_with_port
74
- protocol + '://' + Awis::API_HOST
75
- end
76
-
77
- def timestamp
78
- @timestamp ||= Time::now.utc.strftime("%Y-%m-%dT%H:%M:%S.000Z")
79
- end
80
-
81
- def signature
82
- Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest.new("sha256"), Awis.config.secret_access_key, sign)).strip
83
- end
84
-
85
- def url_params
86
- '?' + original_params
87
- end
88
-
89
- def request_url
90
- URI.parse(host_with_port + url_params)
91
- end
92
-
93
- def default_params
94
- {
95
- "AWSAccessKeyId" => Awis.config.access_key_id,
96
- "SignatureMethod" => "HmacSHA256",
97
- "SignatureVersion" => Awis::API_SIGNATURE_VERSION,
98
- "Timestamp" => timestamp,
99
- "Version" => Awis::API_VERSION
100
- }
101
- end
102
-
103
- def sign
104
- "GET\n" + Awis::API_HOST + "\n/\n" + query_params
105
- end
106
-
107
- def query_params
108
- default_params.merge(params).map { |key, value| "#{key}=#{CGI::escape(value.to_s)}" }.sort.join("&")
109
- end
110
-
111
- def original_params
112
- query_params + "&Signature=" + CGI::escape(signature)
32
+ response = handle_response(request)
33
+ response.body.force_encoding(Encoding::UTF_8)
113
34
  end
114
35
  end
115
36
  end
@@ -2,4 +2,12 @@ class Hash
2
2
  def array_slice_merge!(key, array, count)
3
3
  self[key] = array.each_slice(count).collect { |e| e.reduce({}, :merge) }
4
4
  end
5
+
6
+ def deep_find(key, object = self, found = nil)
7
+ return object[key] if object.respond_to?(:key?) && object.key?(key)
8
+ return found unless object.is_a?(Enumerable)
9
+
10
+ object.find { |*a| found = deep_find(key, a.last) }
11
+ found
12
+ end
5
13
  end
@@ -0,0 +1,9 @@
1
+ require "awis/utils/extra"
2
+ require "awis/utils/variable"
3
+ require "awis/utils/request"
4
+
5
+ module Awis
6
+ module Utils
7
+ autoload :XML, "awis/utils/xml"
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class Hash
2
+ def deep_find(key, object = self, found = nil)
3
+ return object[key] if object.respond_to?(:key?) && object.key?(key)
4
+ return found unless object.is_a?(Enumerable)
5
+
6
+ object.find { |*a| found = deep_find(key, a.last) }
7
+ found
8
+ end
9
+ end
@@ -0,0 +1,153 @@
1
+ require "cgi"
2
+ require "base64"
3
+ require "openssl"
4
+ require "uri"
5
+ require "net/https"
6
+ require "time"
7
+ require 'pry'
8
+
9
+ module Awis
10
+ module Utils
11
+ module Request
12
+ def signature_key(key, date_stamp, region_name, service_name)
13
+ kDate = openssl_hmac_digest(encryption_method, aws4 + key, date_stamp)
14
+ kRegion = openssl_hmac_digest(encryption_method, kDate, region_name)
15
+ kService = openssl_hmac_digest(encryption_method, kRegion, service_name)
16
+ kSigning = openssl_hmac_digest(encryption_method, kService, aws4_request)
17
+ kSigning
18
+ end
19
+
20
+ # escape str to RFC 3986
21
+ def escapeRFC3986(str)
22
+ URI.escape(str, /[^A-Za-z0-9\-_.~]/)
23
+ end
24
+
25
+ def timestamp
26
+ Time::now.utc.strftime("%Y%m%dT%H%M%SZ")
27
+ end
28
+
29
+ def datestamp
30
+ Time::now.utc.strftime("%Y%m%d")
31
+ end
32
+
33
+ def headers
34
+ {
35
+ "host" => Awis::SERVICE_ENDPOINT,
36
+ "x-amz-date" => timestamp
37
+ }
38
+ end
39
+
40
+ def query_str
41
+ params.sort.map{|k,v| k + "=" + escapeRFC3986(v.to_s())}.join('&')
42
+ end
43
+
44
+ def headers_str
45
+ headers.sort.map{|k,v| k + ":" + v}.join("\n") + "\n"
46
+ end
47
+
48
+ def headers_lst
49
+ headers.sort.map{|k,v| k}.join(";")
50
+ end
51
+
52
+ def payload_hash
53
+ digest_sha256_hexdigest ""
54
+ end
55
+
56
+ def canonical_request
57
+ "GET" + "\n" + Awis::SERVICE_URI + "\n" + query_str + "\n" + headers_str + "\n" + headers_lst + "\n" + payload_hash
58
+ end
59
+
60
+ def algorithm
61
+ "AWS4-HMAC-SHA256"
62
+ end
63
+
64
+ def credential_scope
65
+ datestamp + "/" + Awis::SERVICE_REGION + "/" + Awis::SERVICE_NAME + "/" + aws4_request
66
+ end
67
+
68
+ def string_to_sign
69
+ algorithm + "\n" + timestamp + "\n" + credential_scope + "\n" + digest_sha256_hexdigest(canonical_request)
70
+ end
71
+
72
+ def signing_key
73
+ signature_key(Awis.config.secret_access_key, datestamp, Awis::SERVICE_REGION, Awis::SERVICE_NAME)
74
+ end
75
+
76
+ def signature
77
+ OpenSSL::HMAC.hexdigest(encryption_method, signing_key, string_to_sign)
78
+ end
79
+
80
+ def authorization_header
81
+ algorithm + " " +
82
+ "Credential=" + Awis.config.access_key_id + "/" + credential_scope + ", " +
83
+ "SignedHeaders=" + headers_lst + ", " +
84
+ "Signature=" + signature;
85
+ end
86
+
87
+ def uri
88
+ URI(url + url_params)
89
+ end
90
+
91
+ def request
92
+ req = Net::HTTP::Get.new(uri.to_s)
93
+ req["Accept"] = "application/xml"
94
+ req["Content-Type"] = "application/xml"
95
+ req["x-amz-date"] = timestamp
96
+ req["Authorization"] = authorization_header
97
+
98
+ response = Net::HTTP.start(uri.host, uri.port,
99
+ use_ssl: uri.scheme == 'https',
100
+ ssl_timeout: @timeout,
101
+ open_timeout: @open_timeout) { |http|
102
+ http.request(req)
103
+ }
104
+
105
+ response
106
+ end
107
+
108
+ def handle_response(response)
109
+ case response.code.to_i
110
+ when 200...300
111
+ response
112
+ when 300...600
113
+ if response.body.nil?
114
+ raise ResponseError.new(nil, response)
115
+ else
116
+ error_message = MultiXml.parse(response.body).deep_find('ErrorCode')
117
+ raise ResponseError.new(error_message, response)
118
+ end
119
+ else
120
+ raise ResponseError.new("Unknown code: #{respnse.code}", response)
121
+ end
122
+ end
123
+
124
+ def aws4
125
+ "AWS4"
126
+ end
127
+
128
+ def aws4_request
129
+ "aws4_request"
130
+ end
131
+
132
+ def encryption_method
133
+ 'sha256'
134
+ end
135
+
136
+ def url
137
+ protocol + '://' + Awis::SERVICE_HOST + Awis::SERVICE_URI
138
+ end
139
+
140
+ def url_params
141
+ '?' + query_str
142
+ end
143
+
144
+ def openssl_hmac_digest(method, key, secret)
145
+ OpenSSL::HMAC.digest(method, key, secret)
146
+ end
147
+
148
+ def digest_sha256_hexdigest(key)
149
+ Digest::SHA256.hexdigest key
150
+ end
151
+ end
152
+ end
153
+ end
@@ -8,7 +8,7 @@ module Awis
8
8
  def each_node(attributes_in_path = false)
9
9
  reader = Nokogiri::XML::Reader(@data)
10
10
  nodes = ['']
11
-
11
+
12
12
  reader.each do |node|
13
13
  if node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT
14
14
  if attributes_in_path && node.attributes.size > 0
@@ -1,3 +1,3 @@
1
1
  module Awis
2
- VERSION = "0.1.1"
2
+ VERSION = "1.0.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: awis-sdk-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2017-08-24 00:00:00.000000000 Z
12
+ date: 2017-12-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: multi_xml
@@ -28,13 +28,13 @@ dependencies:
28
28
  - !ruby/object:Gem::Version
29
29
  version: 0.5.0
30
30
  - !ruby/object:Gem::Dependency
31
- name: faraday
31
+ name: nokogiri
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  none: false
34
34
  requirements:
35
35
  - - ~>
36
36
  - !ruby/object:Gem::Version
37
- version: 0.9.0
37
+ version: 1.6.8
38
38
  type: :runtime
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
@@ -42,25 +42,25 @@ dependencies:
42
42
  requirements:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
- version: 0.9.0
45
+ version: 1.6.8
46
46
  - !ruby/object:Gem::Dependency
47
- name: nokogiri
47
+ name: minitest
48
48
  requirement: !ruby/object:Gem::Requirement
49
49
  none: false
50
50
  requirements:
51
- - - ~>
51
+ - - ! '>='
52
52
  - !ruby/object:Gem::Version
53
- version: 1.6.8
54
- type: :runtime
53
+ version: '0'
54
+ type: :development
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  none: false
58
58
  requirements:
59
- - - ~>
59
+ - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
- version: 1.6.8
61
+ version: '0'
62
62
  - !ruby/object:Gem::Dependency
63
- name: minitest
63
+ name: mocha
64
64
  requirement: !ruby/object:Gem::Requirement
65
65
  none: false
66
66
  requirements:
@@ -76,7 +76,7 @@ dependencies:
76
76
  - !ruby/object:Gem::Version
77
77
  version: '0'
78
78
  - !ruby/object:Gem::Dependency
79
- name: mocha
79
+ name: webmock
80
80
  requirement: !ruby/object:Gem::Requirement
81
81
  none: false
82
82
  requirements:
@@ -92,7 +92,7 @@ dependencies:
92
92
  - !ruby/object:Gem::Version
93
93
  version: '0'
94
94
  - !ruby/object:Gem::Dependency
95
- name: webmock
95
+ name: pry
96
96
  requirement: !ruby/object:Gem::Requirement
97
97
  none: false
98
98
  requirements:
@@ -143,7 +143,10 @@ files:
143
143
  - lib/awis/models/sites_linking_in.rb
144
144
  - lib/awis/models/traffic_history.rb
145
145
  - lib/awis/models/url_info.rb
146
+ - lib/awis/utils.rb
146
147
  - lib/awis/utils/extra.rb
148
+ - lib/awis/utils/hash.rb
149
+ - lib/awis/utils/request.rb
147
150
  - lib/awis/utils/variable.rb
148
151
  - lib/awis/utils/xml.rb
149
152
  - lib/awis/version.rb
@@ -167,10 +170,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
167
170
  version: '0'
168
171
  segments:
169
172
  - 0
170
- hash: 862568070736027421
173
+ hash: -1995395337547775
171
174
  requirements: []
172
175
  rubyforge_project:
173
- rubygems_version: 1.8.23
176
+ rubygems_version: 1.8.23.2
174
177
  signing_key:
175
178
  specification_version: 3
176
179
  summary: Ruby - Amazon Alexa Web Information Service Library (AWIS)