lib/amazon/ecs.rb in amazon-ecs-0.5.4 vs lib/amazon/ecs.rb in amazon-ecs-0.5.5
- old
+ new
@@ -1,7 +1,7 @@
#--
-# Copyright (c) 2006 Herryanto Siatono, Pluit Solutions
+# Copyright (c) 2009 Herryanto Siatono, Pluit Solutions
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
@@ -22,24 +22,30 @@
#++
require 'net/http'
require 'hpricot'
require 'cgi'
+require 'hmac-sha2'
+require 'base64'
module Amazon
class RequestError < StandardError; end
class Ecs
- 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'
+ SERVICE_URLS = {:us => 'http://webservices.amazon.com/onca/xml?',
+ :uk => 'http://webservices.amazon.co.uk/onca/xml?',
+ :ca => 'http://webservices.amazon.ca/onca/xml?',
+ :de => 'http://webservices.amazon.de/onca/xml?',
+ :jp => 'http://webservices.amazon.co.jp/onca/xml?',
+ :fr => 'http://webservices.amazon.fr/onca/xml?'
}
- @@options = {}
+ @@options = {
+ :version => "2009-01-06",
+ :service => "AWSECommerceService"
+ }
+
@@debug = false
# Default search options
def self.options
@@options
@@ -90,10 +96,14 @@
end
# Generic send request to ECS REST service. You have to specify the :operation parameter.
def self.send_request(opts)
opts = self.options.merge(opts) if self.options
+
+ # Include other required options
+ opts[:timestamp] = Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
+
request_url = prepare_url(opts)
log "Request URL: #{request_url}"
res = Net::HTTP.get_response(URI::parse(request_url))
unless res.kind_of? Net::HTTPSuccess
@@ -188,22 +198,42 @@
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
+
+ secret_key = opts.delete(:aWS_secret_key)
+ request_host = URI.parse(request_url).host
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)}"
+ opts.collect {|a,b| [camelize(a.to_s), b.to_s] }.sort {|c,d| c[0].to_s <=> d[0].to_s}.each {|e|
+ log "Adding #{e[0]}=#{e[1]}"
+ next unless e[1]
+ e[1] = e[1].join(',') if e[1].is_a? Array
+ v=URI.encode(e[1].to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
+ qs << "&" unless qs.length == 0
+ qs << "#{e[0]}=#{v}"
}
- "#{request_url}#{qs}"
+
+ signature = ''
+ unless secret_key.nil?
+ request_to_sign="GET\n#{request_host}\n/onca/xml\n#{qs}"
+ signature = "&Signature=#{sign_request(request_to_sign, secret_key)}"
+ end
+
+ "#{request_url}#{qs}#{signature}"
end
def self.camelize(s)
s.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
end
+
+ def self.sign_request(url, key)
+ return nil if key.nil?
+ signature = URI.escape( Base64.encode64( HMAC::SHA256.digest(key, url) ).strip, Regexp.new("[+=]") )
+ return signature
+ end
+
end
# Internal wrapper class to provide convenient method to access Hpricot element value.
class Element
# Pass Hpricot::Elements object
\ No newline at end of file