amazon-mws 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/.gitignore +1 -0
  2. data/README.markdown +31 -0
  3. data/Rakefile +14 -0
  4. data/VERSION +1 -0
  5. data/amazon-mws.gemspec +164 -0
  6. data/examples/xml/cancel_feed_submissions.xml +16 -0
  7. data/examples/xml/cancel_report_requests.xml +18 -0
  8. data/examples/xml/error.xml +10 -0
  9. data/examples/xml/get_feed_submission_count.xml +10 -0
  10. data/examples/xml/get_feed_submission_list.xml +16 -0
  11. data/examples/xml/get_feed_submission_list_by_next_token.xml +16 -0
  12. data/examples/xml/get_feed_submission_result.xml +30 -0
  13. data/examples/xml/get_report_count.xml +9 -0
  14. data/examples/xml/get_report_list.xml +17 -0
  15. data/examples/xml/get_report_request_count.xml +8 -0
  16. data/examples/xml/get_report_request_list.xml +120 -0
  17. data/examples/xml/get_report_request_list_by_next_token.xml +20 -0
  18. data/examples/xml/get_report_schedule_count.xml +10 -0
  19. data/examples/xml/get_report_schedule_list.xml +15 -0
  20. data/examples/xml/get_report_schedule_list_by_next_token.xml +15 -0
  21. data/examples/xml/manage_report_schedule.xml +14 -0
  22. data/examples/xml/request_report.xml +17 -0
  23. data/examples/xml/submit_feed.xml +14 -0
  24. data/examples/xml/update_report_acknowledgements.xml +18 -0
  25. data/examples/xsd/Inventory.xsd +49 -0
  26. data/examples/xsd/Item.xsd +285 -0
  27. data/examples/xsd/Listings.xsd +32 -0
  28. data/examples/xsd/OrderAcknowledgement.xsd +55 -0
  29. data/examples/xsd/OrderAdjustment.xsd +94 -0
  30. data/examples/xsd/OrderFulfillment.xsd +57 -0
  31. data/examples/xsd/Override.xsd +48 -0
  32. data/examples/xsd/Price.xsd +59 -0
  33. data/examples/xsd/ProcessingReport.xsd +87 -0
  34. data/examples/xsd/Product.xsd +220 -0
  35. data/examples/xsd/Product/AutoAccessory.xsd +807 -0
  36. data/examples/xsd/Product/Beauty.xsd +114 -0
  37. data/examples/xsd/Product/CE.xsd +544 -0
  38. data/examples/xsd/Product/CameraPhoto.xsd +2410 -0
  39. data/examples/xsd/Product/FoodAndBeverages.xsd +270 -0
  40. data/examples/xsd/Product/Gourmet.xsd +85 -0
  41. data/examples/xsd/Product/Health.xsd +189 -0
  42. data/examples/xsd/Product/Home.xsd +654 -0
  43. data/examples/xsd/Product/Jewelry.xsd +603 -0
  44. data/examples/xsd/Product/Miscellaneous.xsd +157 -0
  45. data/examples/xsd/Product/MusicalInstruments.xsd +853 -0
  46. data/examples/xsd/Product/Office.xsd +550 -0
  47. data/examples/xsd/Product/PetSupplies.xsd +40 -0
  48. data/examples/xsd/Product/ProductClothing.xsd +197 -0
  49. data/examples/xsd/Product/SWVG.xsd +238 -0
  50. data/examples/xsd/Product/Sports.xsd +308 -0
  51. data/examples/xsd/Product/TiresAndWheels.xsd +159 -0
  52. data/examples/xsd/Product/Tools.xsd +66 -0
  53. data/examples/xsd/Product/ToysBaby.xsd +241 -0
  54. data/examples/xsd/Product/Wireless.xsd +77 -0
  55. data/examples/xsd/ProductImage.xsd +39 -0
  56. data/examples/xsd/Relationship.xsd +47 -0
  57. data/examples/xsd/SettlementReport.xsd +158 -0
  58. data/examples/xsd/amzn-base.xsd +1601 -0
  59. data/examples/xsd/amzn-envelope.xsd +98 -0
  60. data/examples/xsd/amzn-header.xsd +45 -0
  61. data/lib/amazon/mws.rb +86 -0
  62. data/lib/amazon/mws/authentication.rb +9 -0
  63. data/lib/amazon/mws/authentication/query_string.rb +28 -0
  64. data/lib/amazon/mws/authentication/signature.rb +43 -0
  65. data/lib/amazon/mws/base.rb +61 -0
  66. data/lib/amazon/mws/connection.rb +99 -0
  67. data/lib/amazon/mws/connection/management.rb +94 -0
  68. data/lib/amazon/mws/connection/request_builder.rb +67 -0
  69. data/lib/amazon/mws/exceptions.rb +80 -0
  70. data/lib/amazon/mws/feed.rb +223 -0
  71. data/lib/amazon/mws/feed_builder.rb +67 -0
  72. data/lib/amazon/mws/feed_enumerations.rb +46 -0
  73. data/lib/amazon/mws/feed_submission.rb +14 -0
  74. data/lib/amazon/mws/lib/extensions.rb +162 -0
  75. data/lib/amazon/mws/lib/memoizable.rb +10 -0
  76. data/lib/amazon/mws/orders.rb +9 -0
  77. data/lib/amazon/mws/report.rb +310 -0
  78. data/lib/amazon/mws/report_enumerations.rb +44 -0
  79. data/lib/amazon/mws/report_info.rb +16 -0
  80. data/lib/amazon/mws/report_request.rb +19 -0
  81. data/lib/amazon/mws/report_schedule.rb +13 -0
  82. data/lib/amazon/mws/response.rb +32 -0
  83. data/lib/amazon/mws/response/cancel_feed_submissions_response.rb +14 -0
  84. data/lib/amazon/mws/response/cancel_report_requests_response.rb +14 -0
  85. data/lib/amazon/mws/response/get_feed_submission_count_response.rb +13 -0
  86. data/lib/amazon/mws/response/get_feed_submission_list_by_next_token_response.rb +15 -0
  87. data/lib/amazon/mws/response/get_feed_submission_list_response.rb +15 -0
  88. data/lib/amazon/mws/response/get_feed_submission_result_response.rb +54 -0
  89. data/lib/amazon/mws/response/get_report_count_response.rb +13 -0
  90. data/lib/amazon/mws/response/get_report_list_response.rb +15 -0
  91. data/lib/amazon/mws/response/get_report_request_count_response.rb +13 -0
  92. data/lib/amazon/mws/response/get_report_request_list_by_next_token_response.rb +15 -0
  93. data/lib/amazon/mws/response/get_report_request_list_response.rb +15 -0
  94. data/lib/amazon/mws/response/get_report_schedule_count_response.rb +13 -0
  95. data/lib/amazon/mws/response/get_report_schedule_list_by_next_token_response.rb +15 -0
  96. data/lib/amazon/mws/response/get_report_schedule_list_response.rb +15 -0
  97. data/lib/amazon/mws/response/manage_report_schedule_response.rb +14 -0
  98. data/lib/amazon/mws/response/request_report_response.rb +14 -0
  99. data/lib/amazon/mws/response/response_error.rb +15 -0
  100. data/lib/amazon/mws/response/submit_feed_response.rb +13 -0
  101. data/lib/amazon/mws/response/update_reports_acknowledgements_response.rb +14 -0
  102. data/lib/amazon/mws/version.rb +12 -0
  103. data/pkg/amazon-mws-0.1.0.gem +0 -0
  104. data/test/authentication_test.rb +15 -0
  105. data/test/connection_test.rb +5 -0
  106. data/test/feed_builder_test.rb +15 -0
  107. data/test/feed_submission_test.rb +32 -0
  108. data/test/feed_test.rb +64 -0
  109. data/test/query_string_test.rb +21 -0
  110. data/test/report_test.rb +29 -0
  111. data/test/request_test.rb +18 -0
  112. data/test/response_test.rb +197 -0
  113. data/test/signature_test.rb +30 -0
  114. data/test/test_config.yml +5 -0
  115. data/test/test_helper.rb +22 -0
  116. metadata +179 -0
@@ -0,0 +1,98 @@
1
+ <?xml version="1.0"?>
2
+ <!-- Revision="$Revision: #6 $" -->
3
+ <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
4
+ <!--
5
+ $Date: 2007/01/18 $
6
+
7
+ AMAZON.COM CONFIDENTIAL. This document and the information contained in it are
8
+ confidential and proprietary information of Amazon.com and may not be reproduced,
9
+ distributed or used, in whole or in part, for any purpose other than as necessary
10
+ to list products for sale on the www.amazon.com web site pursuant to an agreement
11
+ with Amazon.com.
12
+ -->
13
+ <xsd:include schemaLocation="amzn-base.xsd"/>
14
+ <xsd:include schemaLocation="amzn-header.xsd"/>
15
+ <xsd:include schemaLocation="FulfillmentCenter.xsd"/>
16
+ <xsd:include schemaLocation="Inventory.xsd"/>
17
+ <xsd:include schemaLocation="Listings.xsd"/>
18
+ <xsd:include schemaLocation="OrderAcknowledgement.xsd"/>
19
+ <xsd:include schemaLocation="OrderAdjustment.xsd"/>
20
+ <xsd:include schemaLocation="OrderFulfillment.xsd"/>
21
+
22
+ <xsd:include schemaLocation="Override.xsd"/>
23
+ <xsd:include schemaLocation="Price.xsd"/>
24
+ <xsd:include schemaLocation="ProcessingReport.xsd"/>
25
+ <xsd:include schemaLocation="ProductImage.xsd"/>
26
+ <xsd:include schemaLocation="Product.xsd"/>
27
+ <xsd:include schemaLocation="Relationship.xsd"/>
28
+ <xsd:include schemaLocation="SettlementReport.xsd"/>
29
+ <xsd:element name="AmazonEnvelope">
30
+ <xsd:complexType>
31
+ <xsd:sequence>
32
+ <xsd:element ref="Header"/>
33
+ <xsd:element name="MessageType">
34
+ <xsd:simpleType>
35
+ <xsd:restriction base="xsd:string">
36
+ <xsd:enumeration value="FulfillmentCenter"/>
37
+ <xsd:enumeration value="Inventory"/>
38
+ <xsd:enumeration value="Listings"/>
39
+ <xsd:enumeration value="OrderAcknowledgement"/>
40
+ <xsd:enumeration value="OrderAdjustment"/>
41
+ <xsd:enumeration value="OrderFulfillment"/>
42
+ <xsd:enumeration value="Override"/>
43
+ <xsd:enumeration value="Price"/>
44
+ <xsd:enumeration value="ProcessingReport"/>
45
+ <xsd:enumeration value="Product"/>
46
+ <xsd:enumeration value="ProductImage"/>
47
+ <xsd:enumeration value="Relationship"/>
48
+ <xsd:enumeration value="SettlementReport"/>
49
+ </xsd:restriction>
50
+ </xsd:simpleType>
51
+ </xsd:element>
52
+ <xsd:element ref="MarketplaceName" minOccurs="0">
53
+ <xsd:annotation>
54
+ <xsd:documentation>
55
+ The MarketplaceName is only supported for
56
+ Override feeds.
57
+ If included here, the MarketplaceName will
58
+ apply to all messages in the feed.
59
+ </xsd:documentation>
60
+ </xsd:annotation>
61
+ </xsd:element>
62
+ <xsd:element name="PurgeAndReplace" type="xsd:boolean" minOccurs="0"/>
63
+ <xsd:element name="EffectiveDate" type="xsd:dateTime" minOccurs="0"/>
64
+ <xsd:element name="Message" maxOccurs="unbounded">
65
+ <xsd:complexType>
66
+ <xsd:sequence>
67
+ <xsd:element name="MessageID" type="IDNumber"/>
68
+ <xsd:element name="OperationType" minOccurs="0">
69
+ <xsd:simpleType>
70
+ <xsd:restriction base="xsd:string">
71
+ <xsd:enumeration value="Update"/>
72
+ <xsd:enumeration value="Delete"/>
73
+ <xsd:enumeration value="PartialUpdate"/>
74
+ </xsd:restriction>
75
+ </xsd:simpleType>
76
+ </xsd:element>
77
+ <xsd:choice>
78
+ <xsd:element ref="FulfillmentCenter"/>
79
+ <xsd:element ref="Inventory"/>
80
+ <xsd:element ref="Listings"/>
81
+ <xsd:element ref="OrderAcknowledgement"/>
82
+ <xsd:element ref="OrderAdjustment"/>
83
+ <xsd:element ref="OrderFulfillment"/>
84
+ <xsd:element ref="Override"/>
85
+ <xsd:element ref="Price"/>
86
+ <xsd:element ref="ProcessingReport"/>
87
+ <xsd:element ref="Product"/>
88
+ <xsd:element ref="ProductImage"/>
89
+ <xsd:element ref="Relationship"/>
90
+ <xsd:element ref="SettlementReport"/>
91
+ </xsd:choice>
92
+ </xsd:sequence>
93
+ </xsd:complexType>
94
+ </xsd:element>
95
+ </xsd:sequence>
96
+ </xsd:complexType>
97
+ </xsd:element>
98
+ </xsd:schema>
@@ -0,0 +1,45 @@
1
+ <?xml version="1.0"?>
2
+ <!-- "$Revision: #3 $" -->
3
+ <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
4
+
5
+ <!--
6
+ $Date: 2005/04/01 $
7
+
8
+ AMAZON.COM CONFIDENTIAL. This document and the information contained in it are
9
+ confidential and proprietary information of Amazon.com and may not be reproduced,
10
+ distributed or used, in whole or in part, for any purpose other than as necessary
11
+ to list products for sale on the www.amazon.com web site pursuant to an agreement
12
+ with Amazon.com.
13
+ -->
14
+
15
+ <xsd:include schemaLocation="amzn-base.xsd"/>
16
+
17
+ <xsd:element name="Header">
18
+ <xsd:complexType>
19
+ <xsd:sequence>
20
+
21
+ <xsd:element name="DocumentVersion">
22
+ <xsd:simpleType>
23
+ <xsd:restriction base="xsd:string">
24
+ <xsd:pattern value="\d{1,2}\.\d{1,2}"/>
25
+ </xsd:restriction>
26
+ </xsd:simpleType>
27
+ </xsd:element>
28
+
29
+ <xsd:element name="MerchantIdentifier" type="String"/>
30
+
31
+ <xsd:element name="OverrideReleaseId" minOccurs="0">
32
+ <xsd:simpleType>
33
+ <xsd:restriction base="xsd:string">
34
+ <xsd:pattern value="\d{1,4}\.\d{1,4}"/>
35
+ </xsd:restriction>
36
+ </xsd:simpleType>
37
+ </xsd:element>
38
+
39
+ </xsd:sequence>
40
+ </xsd:complexType>
41
+ </xsd:element>
42
+
43
+ </xsd:schema>
44
+
45
+
@@ -0,0 +1,86 @@
1
+ require 'rubygems'
2
+ require 'cgi'
3
+ require 'uri'
4
+ require 'openssl'
5
+ require 'net/https'
6
+ require 'time'
7
+ require 'date'
8
+ require 'hmac'
9
+ require 'hmac-sha2'
10
+ require 'base64'
11
+ require 'builder'
12
+ require "rexml/document"
13
+
14
+ # ROXML - nokogiri and roxml are the only dependencies
15
+ I_KNOW_I_AM_USING_AN_OLD_AND_BUGGY_VERSION_OF_LIBXML2 = true
16
+ # module ROXML
17
+ # XML_PARSER = 'nokogiri' # or 'libxml'
18
+ # end
19
+ require 'roxml'
20
+ # /ROXML
21
+
22
+
23
+ $:.unshift(File.dirname(__FILE__))
24
+ require 'mws/lib/extensions'
25
+ require 'builder'
26
+ #require_library_or_gem 'mime/types', 'mime-types' unless defined? MIME::Types
27
+
28
+ module Amazon
29
+ module MWS
30
+ end
31
+ end
32
+
33
+
34
+
35
+ require 'mws/lib/memoizable'
36
+
37
+ require 'mws/feed_builder'
38
+ require 'mws/feed_enumerations'
39
+ require 'mws/feed'
40
+ require 'mws/report_enumerations'
41
+ require 'mws/report'
42
+
43
+
44
+ require 'mws/response'
45
+ require 'mws/feed_submission'
46
+ require 'mws/report_request'
47
+ require 'mws/report_info'
48
+ require 'mws/report_schedule'
49
+ Dir.glob(File.join(File.dirname(__FILE__), 'mws/response/*.rb')).each {|f| require f }
50
+
51
+ require 'mws/base'
52
+ require 'mws/version'
53
+ require 'mws/exceptions'
54
+ require 'mws/connection'
55
+ require 'mws/connection/management'
56
+ require 'mws/connection/request_builder'
57
+ require 'mws/authentication'
58
+ require 'mws/authentication/query_string'
59
+ require 'mws/authentication/signature'
60
+
61
+
62
+ Amazon::MWS::Base.class_eval do
63
+ include Amazon::MWS::Feed
64
+ include Amazon::MWS::Report
65
+ end
66
+
67
+ AWS = Amazon
68
+
69
+ require_library_or_gem 'xmlsimple', 'xml-simple' unless defined? XmlSimple
70
+ =begin
71
+ # If libxml is installed, we use the FasterXmlSimple library, that provides most of the functionality of XmlSimple
72
+ # except it uses the xml/libxml library for xml parsing (rather than REXML). If libxml isn't installed, we just fall back on
73
+ # XmlSimple.
74
+ AWS::S3::Parsing.parser =
75
+ begin
76
+ require_library_or_gem 'xml/libxml'
77
+ # Older version of libxml aren't stable (bus error when requesting attributes that don't exist) so we
78
+ # have to use a version greater than '0.3.8.2'.
79
+ raise LoadError unless XML::Parser::VERSION > '0.3.8.2'
80
+ $:.push(File.join(File.dirname(__FILE__), '..', '..', 'support', 'faster-xml-simple', 'lib'))
81
+ require_library_or_gem 'faster_xml_simple'
82
+ FasterXmlSimple
83
+ rescue LoadError
84
+ XmlSimple
85
+ end
86
+ =end
@@ -0,0 +1,9 @@
1
+ module Amazon
2
+ module MWS
3
+ class Authentication
4
+ VERSION = '2009-01-01'
5
+ # Nothing really to see here,
6
+ # please have a look at the files in the authentication folder
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,28 @@
1
+ class Amazon::MWS::Authentication
2
+
3
+ class QueryString < String
4
+ def initialize(params = {})
5
+ query_params = {
6
+ 'AWSAccessKeyId' => params[:access_key],
7
+ 'Marketplace' => params[:marketplace_id],
8
+ 'Merchant' => params[:merchant_id],
9
+ 'SignatureMethod' => Signature::METHOD,
10
+ 'SignatureVersion' => Signature::VERSION,
11
+ 'Timestamp' => Time.now.iso8601,
12
+ 'Version' => Amazon::MWS::Authentication::VERSION
13
+ }
14
+
15
+ # Add any params that are passed in via uri before calculating the signature
16
+ query_params = query_params.merge(params[:query_params] || {})
17
+ # Calculate the signature
18
+ query_params['Signature'] = Signature.new(query_params, params)
19
+
20
+ self << formatted_querystring(query_params)
21
+ end
22
+
23
+ def formatted_querystring(query_params)
24
+ query_params.collect { |key, value| [CGI.escape(key.to_s), CGI.escape(value.to_s)].join('=') }.join('&') # order doesn't matter for the actual request
25
+ end
26
+ end
27
+
28
+ end
@@ -0,0 +1,43 @@
1
+ class Amazon::MWS::Authentication
2
+
3
+ class Signature < String#:nodoc:
4
+ extend Memoizable
5
+
6
+ VERSION = '2'
7
+ METHOD = 'HmacSHA256'
8
+
9
+ def initialize(queryparams = {}, params = {})
10
+ verb = params[:verb]
11
+ secret = params[:secret_access_key]
12
+ # Create the string to sign
13
+ string = string_to_sign(verb, canonical_querystring(queryparams))
14
+ self << sign(string, secret)
15
+ end
16
+
17
+ # Returns a signed string
18
+ def sign(string, secret_access_key)
19
+ hmac = HMAC::SHA256.new(secret_access_key)
20
+ hmac.update(string)
21
+ # chomp is important! the base64 encoded version will have a newline at the end
22
+ Base64.encode64(hmac.digest).chomp
23
+ end
24
+
25
+ memoize :sign
26
+
27
+ def string_to_sign(verb, querystring)
28
+ verb = verb.to_s.upcase
29
+ string = "#{verb}\n#{Amazon::MWS::DEFAULT_HOST}\n/\n#{querystring}"
30
+ end
31
+
32
+ memoize :string_to_sign
33
+
34
+ def canonical_querystring(params)
35
+ # Make sure we have string keys, otherwise the sort does not work
36
+ params = Hash.keys_to_s(params)
37
+ params.sort.collect { |key, value| [CGI.escape(key.to_s), CGI.escape(value.to_s)].join('=') }.join('&')
38
+ end
39
+
40
+ memoize :canonical_querystring
41
+ end
42
+
43
+ end
@@ -0,0 +1,61 @@
1
+ module Amazon
2
+ module MWS
3
+ DEFAULT_HOST = "mws.amazonaws.com"
4
+
5
+ class Base
6
+ attr_accessor :connection
7
+
8
+ def self.debug; @@debug ||= false end
9
+ def self.debug=(bool); @@debug = bool end
10
+
11
+ def initialize(options ={})
12
+ @connection = Amazon::MWS::Connection.connect(options)
13
+ end
14
+
15
+ def connection
16
+ raise Amazon::MWS::NoConnectionEstablished.new if !connected?
17
+ @connection
18
+ end
19
+
20
+ def connected?
21
+ !@connection.nil?
22
+ end
23
+
24
+ def disconnect
25
+ @connection.http.finish if @connection.persistent?
26
+ @connection = nil
27
+ end
28
+
29
+ # Wraps the current connection's request method and picks the appropriate response class to wrap the response in.
30
+ # If the response is an error, it will raise that error as an exception. All such exceptions can be caught by rescuing
31
+ # their superclass, the ResponseError exception class.
32
+ #
33
+ # It is unlikely that you would call this method directly. Subclasses of Base have convenience methods for each http request verb
34
+ # that wrap calls to request.
35
+ def request(verb, path, query_params = {}, body = nil, attempts = 0, &block)
36
+ # Find the connection method in connection/management.rb which is evaled into Amazon::MWS::Base
37
+ response = @connection.request(verb, path, query_params, body, attempts, &block)
38
+
39
+ # Each calling class is responsible for formatting the result
40
+ return response
41
+ rescue InternalError, RequestTimeout
42
+ if attempts == 3
43
+ raise
44
+ else
45
+ attempts += 1
46
+ retry
47
+ end
48
+ end
49
+
50
+ # Make some convenience methods
51
+ [:get, :post, :put, :delete, :head].each do |verb|
52
+ class_eval(<<-EVAL, __FILE__, __LINE__)
53
+ def #{verb}(path, query_params = {}, body = nil, &block)
54
+ request(:#{verb}, path, query_params, body, &block)
55
+ end
56
+ EVAL
57
+ end
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,99 @@
1
+ module Amazon
2
+ module MWS
3
+
4
+ class Connection
5
+ # Static/Class methods
6
+ class << self
7
+ def connect(options = {})
8
+ new(options)
9
+ end
10
+ end
11
+
12
+ def initialize(params = {})
13
+ # These values are essential to establishing a connection
14
+ @server = params['server'] || Amazon::MWS::DEFAULT_HOST
15
+ @persistent = params['persistent'] || false
16
+ # These values are essential to signing requests
17
+ @access_key = params['access_key']
18
+ @secret_access_key = params['secret_access_key']
19
+ @merchant_id = params['merchant_id']
20
+ @marketplace_id = params['marketplace_id']
21
+
22
+ raise MissingConnectionOptions if [@access_key, @secret_access_key, @merchant_id, @marketplace_id].any? {|option| option.nil?}
23
+
24
+ @http = connect
25
+ end
26
+
27
+ # Create the Net::HTTP object to use for this connection
28
+ def connect
29
+ http = Net::HTTP.new(@server, 443)
30
+ http.use_ssl = true
31
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
32
+ return http
33
+ end
34
+
35
+ # Make the request, based on the apropriate request object
36
+ # Called from Amazon::MWS::Base
37
+ def request(verb, path, query_params, body = nil, attempts = 0, &block)
38
+ # presumably this is for files
39
+ body.rewind if body.respond_to?(:rewind) unless attempts.zero?
40
+ # Prepare the Proc to be called by Net::HTTP
41
+ proc = requester(verb, path, query_params, body)
42
+
43
+ if @persistent
44
+ @http.start unless @http.started?
45
+ proc.call
46
+ else
47
+ @http.start(&proc)
48
+ end
49
+ rescue Errno::EPIPE, Timeout::Error, Errno::EINVAL, EOFError
50
+ @http = connect
51
+ attempts == 3 ? raise : (attempts += 1; retry)
52
+ end
53
+
54
+ # A Proc used by the request method
55
+ def requester(verb, path, query_params, body)
56
+ Proc.new do |http|
57
+ path = prepare_path(verb, path, query_params)
58
+ puts "#{path}\n\n" if AWS::MWS::Base.debug
59
+ request = build_request(verb, path, body)
60
+
61
+ @http.request(request)
62
+ end
63
+ end
64
+
65
+ # Create the signed authentication query string.
66
+ # Add this query string to the path WITHOUT prepending the server address.
67
+ def prepare_path(verb, path, query_params)
68
+ query_string = authenticate_query_string(verb, query_params)
69
+ return "#{path}?#{query_string}"
70
+ end
71
+
72
+ # Generates the authentication query string used by Amazon.
73
+ # Takes the http method and the query string of the request and returns the authenticated query string
74
+ def authenticate_query_string(verb, query_params = {})
75
+ Authentication::QueryString.new(
76
+ :verb => verb,
77
+ :query_params => query_params,
78
+ :access_key => @access_key,
79
+ :secret_access_key => @secret_access_key,
80
+ :merchant_id => @merchant_id,
81
+ :marketplace_id => @marketplace_id
82
+ )
83
+ end
84
+
85
+ # Builds up a Net::HTTP request object
86
+ def build_request(verb, path, body = nil)
87
+ builder = RequestBuilder.new(verb, path, body)
88
+ builder.add_user_agent
89
+ builder.add_content_type
90
+ builder.add_content_md5(body) unless body.nil?
91
+
92
+ return builder.request
93
+ end
94
+ end
95
+ # Connection
96
+
97
+ end
98
+ end
99
+