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
196 197 198 199 200 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 196 def self.camelize(s) s.to_s .gsub(%r{/(.?)}) { "::" + Regexp.last_match[1].upcase } .gsub(/(^|_)(.)/) { Regexp.last_match[2].upcase } end |
.configure {|@@options| ... } ⇒ Object
57 58 59 60 61 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 57 def self.configure(&_proc) raise ArgumentError, "Block is required." unless block_given? yield @@options end |
.debug ⇒ Object
Get debug flag.
48 49 50 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 48 def self.debug @@debug end |
.debug=(dbg) ⇒ Object
Set debug flag to true or false.
53 54 55 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 53 def self.debug=(dbg) @@debug = dbg end |
.hmac_sha256(message, key) ⇒ Object
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 202 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 = "" (0..key.size - 1).each do |i| 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.
81 82 83 84 85 86 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 81 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].
66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 66 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
34 35 36 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 34 def self. @@options end |
.options=(opts) ⇒ Object
Set default search options
43 44 45 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 43 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
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 176 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 do |k, v| next unless v v = v.join(",") if v.is_a? Array qs << "&#{camelize(k.to_s)}=#{URI.encode(v.to_s)}" end 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
38 39 40 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 38 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.
96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 96 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
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 237 def self.sign_request(request) raise AmazonNotConfiguredError unless @@secret_access_key # Step 0 : Split apart request string url_pattern = %r{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
89 90 91 92 |
# File 'lib/alexandria/book_providers/amazon_ecs_util.rb', line 89 def self.transport config = Alexandria::Preferences.instance.http_proxy_config config ? Net::HTTP.Proxy(*config) : Net::HTTP end |