Class: Amazon::Ecs
- Inherits:
-
Object
- Object
- Amazon::Ecs
- Includes:
- Alexandria::Logging
- Defined in:
- lib/alexandria/book_providers/amazon_ecs_util.rb
Defined Under Namespace
Classes: Response
Constant Summary collapse
- SERVICE_URLS =
{ us: 'http://webservices.amazon.com/onca/xml?Service=AWSECommerceService', uk: 'http://webservices.amazon.co.uk/onca/xml?Service=AWSECommerceService', ca: 'http://webservices.amazon.ca/onca/xml?Service=AWSECommerceService', de: 'http://webservices.amazon.de/onca/xml?Service=AWSECommerceService', jp: 'http://webservices.amazon.co.jp/onca/xml?Service=AWSECommerceService', fr: 'http://webservices.amazon.fr/onca/xml?Service=AWSECommerceService' }.freeze
- @@options =
{}
- @@debug =
false
- @@secret_access_key =
''
Class Method Summary collapse
- .camelize(s) ⇒ Object
- .configure {|@@options| ... } ⇒ Object
-
.debug ⇒ Object
Get debug flag.
-
.debug=(dbg) ⇒ Object
Set debug flag to true or false.
- .hmac_sha256(message, key) ⇒ Object
-
.item_lookup(item_id, opts = {}) ⇒ Object
Search an item by ASIN no.
-
.item_search(terms, opts = {}) ⇒ Object
Search amazon items with search terms.
-
.options ⇒ Object
Default search options.
-
.options=(opts) ⇒ Object
Set default search options.
-
.prepare_url(opts) ⇒ Object
protected def self.log(s) return unless self.debug if defined? RAILS_DEFAULT_LOGGER RAILS_DEFAULT_LOGGER.error(s) elsif defined? LOGGER LOGGER.error(s) else puts s end end.
- .secret_access_key=(key) ⇒ Object
-
.send_request(opts) ⇒ Object
Generic send request to ECS REST service.
- .sign_request(request) ⇒ Object
-
.transport ⇒ Object
HACK : copied from book_providers.rb.
Methods included from Alexandria::Logging
Class Method Details
.camelize(s) ⇒ Object
215 216 217 218 219 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 215 def self.camelize(s) s.to_s. gsub(/\/(.?)/) { '::' + Regexp.last_match[1].upcase }. gsub(/(^|_)(.)/) { Regexp.last_match[2].upcase } end |
.configure {|@@options| ... } ⇒ Object
81 82 83 84 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 81 def self.configure(&_proc) raise ArgumentError, 'Block is required.' unless block_given? yield @@options end |
.debug ⇒ Object
Get debug flag.
72 73 74 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 72 def self.debug @@debug end |
.debug=(dbg) ⇒ Object
Set debug flag to true or false.
77 78 79 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 77 def self.debug=(dbg) @@debug = dbg end |
.hmac_sha256(message, key) ⇒ Object
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 221 def self.hmac_sha256(, key) block_size = 64 ipad = "\x36" * block_size opad = "\x5c" * block_size if key.size > block_size d = Digest::SHA256.new key = d.digest(key) end ipad_bytes = ipad.bytes.map { |b| b } opad_bytes = opad.bytes.map { |b| b } key_bytes = key.bytes.map { |b| b } ipad_xor = '' opad_xor = '' for i in 0..key.size - 1 ipad_xor << (ipad_bytes[i] ^ key_bytes[i]) opad_xor << (opad_bytes[i] ^ key_bytes[i]) end ipad = ipad_xor + ipad[key.size..-1] opad = opad_xor + opad[key.size..-1] # inner hash d1 = Digest::SHA256.new d1.update(ipad) d1.update() msg_hash = d1.digest # outer hash d2 = Digest::SHA256.new d2.update(opad) d2.update(msg_hash) d2.digest end |
.item_lookup(item_id, opts = {}) ⇒ Object
Search an item by ASIN no.
103 104 105 106 107 108 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 103 def self.item_lookup(item_id, opts = {}) opts[:operation] = 'ItemLookup' opts[:item_id] = item_id send_request(opts) end |
.item_search(terms, opts = {}) ⇒ Object
Search amazon items with search terms. Default search index option is ‘Books’. For other search type other than keywords, please specify :type => [search type param name].
88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 88 def self.item_search(terms, opts = {}) opts[:operation] = 'ItemSearch' opts[:search_index] = opts[:search_index] || 'Books' type = opts.delete(:type) if type opts[type.to_sym] = terms else opts[:keywords] = terms end send_request(opts) end |
.options ⇒ Object
Default search options
58 59 60 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 58 def self. @@options end |
.options=(opts) ⇒ Object
Set default search options
67 68 69 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 67 def self.(opts) @@options = opts end |
.prepare_url(opts) ⇒ Object
protected
def self.log(s)
return unless self.debug
if defined? RAILS_DEFAULT_LOGGER
RAILS_DEFAULT_LOGGER.error(s)
elsif defined? LOGGER
LOGGER.error(s)
else
puts s
end
end
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 196 def self.prepare_url(opts) country = opts.delete(:country) country = country.nil? ? 'us' : country request_url = SERVICE_URLS[country.to_sym] raise Amazon::RequestError, "Invalid country '#{country}'" unless request_url qs = '' opts.each { |k, v| next unless v v = v.join(',') if v.is_a? Array qs << "&#{camelize(k.to_s)}=#{URI.encode(v.to_s)}" } url = "#{request_url}#{qs}" # puts ">>> base url >> #{url}" signed_url = sign_request(url) # puts ">>> SIGNED >> #{signed_url}" signed_url end |
.secret_access_key=(key) ⇒ Object
62 63 64 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 62 def self.secret_access_key=(key) @@secret_access_key = key end |
.send_request(opts) ⇒ Object
Generic send request to ECS REST service. You have to specify the :operation parameter.
117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 117 def self.send_request(opts) opts = .merge(opts) if request_url = prepare_url(opts) log.debug { "Request URL: #{request_url}" } res = transport.get_response(URI.parse(request_url)) unless res.is_a? Net::HTTPSuccess raise Amazon::RequestError, "HTTP Response: #{res.code} #{res.}" end Response.new(res.body) end |
.sign_request(request) ⇒ Object
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 256 def self.sign_request(request) raise AmazonNotConfiguredError unless @@secret_access_key # Step 0 : Split apart request string url_pattern = /http:\/\/([^\/]+)(\/[^\?]+)\?(.*$)/ url_pattern =~ request host = Regexp.last_match[1] path = Regexp.last_match[2] param_string = Regexp.last_match[3] # Step 1: enter the timestamp t = Time.now.getutc # MUST be in UTC stamp = t.strftime('%Y-%m-%dT%H:%M:%SZ') param_string += "&Timestamp=#{stamp}" # Step 2 : URL-encode param_string = param_string.gsub(',', '%2C').gsub(':', '%3A') # NOTE : take care not to double-encode # Step 3 : Split the parameter/value pairs params = param_string.split('&') # Step 4 : Sort params params.sort! # Step 5 : Rejoin the param string canonical_param_string = params.join('&') # Steps 6 & 7: Prepend HTTP request info string_to_sign = "GET\n#{host}\n#{path}\n#{canonical_param_string}" # puts string_to_sign # Step 8 : Calculate RFC 2104-compliant HMAC with SHA256 hash algorithm sig = hmac_sha256(string_to_sign, @@secret_access_key) base64_sig = [sig].pack('m').strip # Step 9 : URL-encode + and = in sig base64_sig = CGI.escape(base64_sig) # Step 10 : Add the URL encoded signature to your request "http://#{host}#{path}?#{param_string}&Signature=#{base64_sig}" end |
.transport ⇒ Object
HACK : copied from book_providers.rb
111 112 113 114 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 111 def self.transport config = Alexandria::Preferences.instance.http_proxy_config config ? Net::HTTP.Proxy(*config) : Net::HTTP end |