lib/sucker/request.rb in sucker-1.2.0 vs lib/sucker/request.rb in sucker-1.3.0.pre
- old
+ new
@@ -1,8 +1,8 @@
-require 'curb'
-require 'openssl'
-require 'ostruct'
+# encoding: utf-8
+
+require 'net/http'
require 'uri'
module Sucker #:nodoc:
# A wrapper around the API request
@@ -12,171 +12,58 @@
:uk => 'ecs.amazonaws.co.uk',
:de => 'ecs.amazonaws.de',
:ca => 'ecs.amazonaws.ca',
:fr => 'ecs.amazonaws.fr',
:jp => 'ecs.amazonaws.jp' }
- PATH = "/onca/xml"
- # The Amazon secret access key
+ # Your Amazon associate tag
+ attr_accessor :associate_tag
+
+ # Your AWS access key
+ attr_accessor :key
+
+ # Local IP to route the request through
+ attr_accessor :local_ip
+
+ # Amazon locale
+ attr_accessor :locale
+
+ # Your AWS secret
attr_accessor :secret
# Initializes a request object
#
# worker = Sucker.new(
- # :key => "API KEY",
- # :secret => "API SECRET")
+ # :key => 'API KEY',
+ # :secret => 'API SECRET')
#
def initialize(args)
args.each { |k, v| send("#{k}=", v) }
end
# Merges a hash into the existing parameters
#
# worker << {
- # "Operation" => "ItemLookup",
- # "IdType" => "ASIN",
- # "ItemId" => "0816614024" }
+ # 'Operation' => 'ItemLookup',
+ # 'IdType' => 'ASIN',
+ # 'ItemId' => '0816614024' }
#
def <<(hash)
self.parameters.merge!(hash)
end
- # Returns the associate tag for the current locale
- def associate_tag
- @associate_tags[locale.to_sym] rescue ''
- end
-
- # Sets the associate tag for the current locale
- #
- # worker.associate_tag = 'foo-bar'
- #
- def associate_tag=(token)
- associate_tags[locale.to_sym] = token
- end
-
- # Gets the associate tags for all locales
- def associate_tags
- @associate_tags ||= {}
- end
-
- # Sets associate tags for all locales
- #
- # You need a distinct associate tag for each locale.
- #
- # tags = {
- # :us => 'foo-bar-10',
- # :uk => 'foo-bar-20',
- # ... }
- #
- # worker.associate_tags = tags
- #
- def associate_tags=(tokens)
- @associate_tags = tokens
- end
-
- # Returns options for curl and yields them if given a block
- #
- # worker.curl_opts { |c| c.interface = "eth1" }
- #
- def curl_opts
- @curl_opts ||= OpenStruct.new
- yield @curl_opts if block_given?
-
- @curl_opts.marshal_dump
- end
-
# Performs a request and returns a response
#
# response = worker.get
#
- # Optionally, pass one or more locales to query specific locales or `:all`
- # to query all locales.
- #
- # responses = worker.get(:us)
- #
- # responses = worker.get(:all)
- #
- def get(*args)
- case args.count
-
- when 0
- curl = Curl::Easy.perform(uri.to_s) do |easy|
- curl_opts.each { |k, v| easy.send("#{k}=", v) }
- end
- Response.new(curl)
-
- when 1
- arg = args.first
- if arg == :all
- get_multi locales
- else
- self.locale = arg
- get
- end
-
- else
- get_multi args
+ def get
+ response = request_through(local_ip) do
+ Net::HTTP.get_response(uri)
end
+ Response.new(response)
end
- def get_all # :nodoc:
- warn "[DEPRECATION] `get_all` is deprecated. Please use `get(:all) instead."
- get(:all)
- end
-
- # Returns the AWS access key for the current locale
- def key
- raise ArgumentError.new "AWS access key missing" unless @keys[locale]
-
- @keys[locale]
- end
-
- # Sets a global AWS access key
- #
- # worker.key = 'foo'
- #
- def key=(token)
- @keys = locales.inject({}) do |keys, locale|
- keys[locale] = token
- keys
- end
- end
-
- # Sets distinct AWS access keys for the locales
- #
- # You can use the same key on multiple venues. Caveat: Calls against (1) the US
- # and Canada and (2) the UK, France, and Germany count against the same call
- # rate quota.
- #
- # keys = {
- # :us => 'foo',
- # :uk => 'bar',
- # ... }
- #
- # worker.keys = keys
- #
- def keys=(tokens)
- @keys = tokens
- end
-
- def locale
- raise ArgumentError.new "Locale not set" unless @locale
-
- @locale
- end
-
- # Sets the current Amazon locale
- #
- # Valid values are :us, :uk, :de, :ca, :fr, and :jp.
- def locale=(new_locale)
- new_locale = new_locale.to_sym
-
- raise ArgumentError.new "Invalid locale" unless locales.include? new_locale
-
- @locale = new_locale
- end
-
# The parameters to query Amazon with
def parameters
@parameters ||= Parameters.new
end
@@ -192,22 +79,22 @@
def build_query
parameters.
normalize.
merge({ 'AWSAccessKeyId' => key }).
- merge({ 'AssociateTag' => associate_tag }).
+ merge({ 'AssociateTag' => associate_tag.to_s }).
sort.
map do |k, v|
"#{k}=" + escape(v)
end.join('&')
end
def build_signed_query
query = build_query
digest = OpenSSL::Digest::Digest.new('sha256')
- string = ['GET', host, PATH, query].join("\n")
+ string = ['GET', host, '/onca/xml', query].join("\n")
hmac = OpenSSL::HMAC.digest(digest, secret, string)
signature = escape([hmac].pack('m').chomp)
query + '&Signature=' + signature
end
@@ -216,33 +103,44 @@
value.gsub(/([^a-zA-Z0-9_.~-]+)/) do
'%' + $1.unpack('H2' * $1.bytesize).join('%').upcase
end
end
- def get_multi(locales)
- responses = []
+ def host
+ HOSTS[locale]
+ end
- Curl::Multi.get(uris, curl_opts) do |curl|
- response = Response.new(curl)
- yield response if block_given?
- responses << response
+ def request_through(local_ip)
+ if local_ip
+ TCPSocket.instance_eval do
+ (class << self; self; end).instance_eval do
+ alias_method :orig_open, :open
+
+ define_method(:open) do |conn_address, conn_port|
+ original_open(conn_address, conn_port, local_ip)
+ end
+ end
+ end
end
- responses
- end
+ return_value = yield
- def host
- HOSTS[locale]
- end
+ if local_ip
+ TCPSocket.instance_eval do
+ (class << self; self; end).instance_eval do
+ alias_method :open, :orig_open
+ remove_method :orig_open
+ end
+ end
+ end
- def locales
- @locales ||= HOSTS.keys
+ return_value
end
def uri
URI::HTTP.build(
:host => host,
- :path => PATH,
+ :path => '/onca/xml',
:query => build_signed_query)
end
def uris
locales.map do |locale|