peddler 1.6.0 → 1.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/mws/merchant_fulfillment/client.rb +2 -0
- data/lib/peddler/client.rb +14 -11
- data/lib/peddler/errors/error.rb +2 -2
- data/lib/peddler/errors/handler.rb +21 -9
- data/lib/peddler/errors/parser.rb +1 -3
- data/lib/peddler/flat_file_parser.rb +10 -19
- data/lib/peddler/headers.rb +2 -0
- data/lib/peddler/vcr_matcher.rb +4 -4
- data/lib/peddler/version.rb +2 -1
- data/test/helper.rb +1 -0
- data/test/integration/test_feeds.rb +10 -8
- data/test/integration/test_reports.rb +1 -7
- data/test/integration_helper.rb +4 -6
- data/test/unit/mws/test_feeds_client.rb +0 -1
- data/test/unit/mws/test_fulfillment_inbound_shipment_client.rb +1 -1
- data/test/unit/mws/test_merchant_fulfillment_client.rb +32 -8
- data/test/unit/peddler/test_client.rb +38 -8
- data/test/unit/peddler/test_flat_file_parser.rb +1 -1
- data/test/unit/peddler/test_headers.rb +5 -0
- data/test/unit/peddler/test_operation.rb +2 -2
- data/test/unit/peddler/test_structured_list.rb +2 -2
- data/test/unit/peddler/test_xml_response_parser.rb +1 -1
- data/test/vcr_cassettes/Feeds.yml +5873 -5454
- data/test/vcr_cassettes/Reports.yml +2785 -4396
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d83b099126be1823bbd9bd9c45ea1d7ec3455f9
|
4
|
+
data.tar.gz: 74b18adc957648244ac9b7bf04d60fe3006c4fc2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7f977ea894c96c6454bfd442bd8f5e866aaf56029c23649d7d133fbca85b4544a894d99e254847a77afaa36460dfb1caf39f0eefb272982739b0c375cf340ba0
|
7
|
+
data.tar.gz: 3b7f7bdf62a91254838b412ba634eca896f8a4cb14683ecb92b7e1621c6a7b72d92874e1a1f564abb0529e390ae85c7cf9cf9fb2d399d9ef695d0f888c6358ac
|
@@ -22,6 +22,7 @@ module MWS
|
|
22
22
|
def get_eligible_shipping_services(shipment_request_details)
|
23
23
|
operation('GetEligibleShippingServices')
|
24
24
|
.add('ShipmentRequestDetails' => shipment_request_details)
|
25
|
+
.structure!('ItemList', 'Item')
|
25
26
|
|
26
27
|
run
|
27
28
|
end
|
@@ -42,6 +43,7 @@ module MWS
|
|
42
43
|
'ShippingServiceId' => shipping_service_id
|
43
44
|
)
|
44
45
|
.add(opts)
|
46
|
+
.structure!('ItemList', 'Item')
|
45
47
|
|
46
48
|
run
|
47
49
|
end
|
data/lib/peddler/client.rb
CHANGED
@@ -129,13 +129,7 @@ module Peddler
|
|
129
129
|
|
130
130
|
# @!parse attr_writer :body
|
131
131
|
def body=(str)
|
132
|
-
|
133
|
-
headers['Content-Type'] = content_type(str)
|
134
|
-
else
|
135
|
-
headers.delete('Content-Type')
|
136
|
-
end
|
137
|
-
|
138
|
-
@body = str
|
132
|
+
str ? add_content(str) : clear_content!
|
139
133
|
end
|
140
134
|
|
141
135
|
# @api private
|
@@ -169,6 +163,7 @@ module Peddler
|
|
169
163
|
opts = build_options
|
170
164
|
opts.store(:response_block, Proc.new) if block_given?
|
171
165
|
res = post(opts)
|
166
|
+
self.body = nil if res.status == 200
|
172
167
|
|
173
168
|
parser.new(res, encoding)
|
174
169
|
rescue Excon::Error => e
|
@@ -181,11 +176,19 @@ module Peddler
|
|
181
176
|
Marketplace.new(primary_marketplace_id)
|
182
177
|
end
|
183
178
|
|
184
|
-
def
|
185
|
-
|
186
|
-
|
179
|
+
def clear_content!
|
180
|
+
headers.delete('Content-Type')
|
181
|
+
@body = nil
|
182
|
+
end
|
183
|
+
|
184
|
+
def add_content(content)
|
185
|
+
if content.start_with?('<?xml')
|
186
|
+
headers['Content-Type'] = 'text/xml'
|
187
|
+
@body = content
|
187
188
|
else
|
188
|
-
|
189
|
+
headers['Content-Type'] =
|
190
|
+
"text/tab-separated-values; charset=#{encoding}"
|
191
|
+
@body = content.encode(encoding)
|
189
192
|
end
|
190
193
|
end
|
191
194
|
|
data/lib/peddler/errors/error.rb
CHANGED
@@ -2,7 +2,7 @@ module Peddler
|
|
2
2
|
# @api private
|
3
3
|
module Errors
|
4
4
|
# Known codes
|
5
|
-
CODES = %w
|
5
|
+
CODES = %w[
|
6
6
|
AccessDenied
|
7
7
|
InvalidMarketplace
|
8
8
|
InvalidParameterValue
|
@@ -10,7 +10,7 @@ module Peddler
|
|
10
10
|
MalformedInput
|
11
11
|
QuotaExceeded
|
12
12
|
RequestThrottled
|
13
|
-
|
13
|
+
].freeze
|
14
14
|
|
15
15
|
# @api private
|
16
16
|
class Error < StandardError
|
@@ -5,6 +5,9 @@ module Peddler
|
|
5
5
|
module Errors
|
6
6
|
# @api private
|
7
7
|
class Handler
|
8
|
+
DIGIT_AS_FIRST_CHAR = /^\d/
|
9
|
+
private_constant :DIGIT_AS_FIRST_CHAR
|
10
|
+
|
8
11
|
def self.call(exception)
|
9
12
|
new(exception).handle
|
10
13
|
end
|
@@ -20,26 +23,35 @@ module Peddler
|
|
20
23
|
end
|
21
24
|
|
22
25
|
def handle
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
28
|
-
rescue NameError
|
29
|
-
raise exception
|
26
|
+
raise exception unless http_status_error?
|
27
|
+
raise exception if bad_name_for_error_class?
|
28
|
+
|
29
|
+
raise error_class.new(error_message, exception)
|
30
30
|
end
|
31
31
|
|
32
32
|
private
|
33
33
|
|
34
34
|
def error_class
|
35
|
-
Errors.const_get(
|
35
|
+
Errors.const_get(error_name)
|
36
36
|
rescue NameError
|
37
|
-
Builder.build(
|
37
|
+
Builder.build(error_name)
|
38
38
|
end
|
39
39
|
|
40
40
|
def http_status_error?
|
41
41
|
exception.is_a?(::Excon::Error::HTTPStatus)
|
42
42
|
end
|
43
|
+
|
44
|
+
def bad_name_for_error_class?
|
45
|
+
error_name =~ DIGIT_AS_FIRST_CHAR
|
46
|
+
end
|
47
|
+
|
48
|
+
def error_name
|
49
|
+
exception.response.code
|
50
|
+
end
|
51
|
+
|
52
|
+
def error_message
|
53
|
+
exception.response.message
|
54
|
+
end
|
43
55
|
end
|
44
56
|
end
|
45
57
|
end
|
@@ -11,20 +11,20 @@ module Peddler
|
|
11
11
|
# http://stackoverflow.com/questions/8073920/importing-csv-quoting-error-is-driving-me-nuts
|
12
12
|
OPTIONS = { col_sep: "\t", quote_char: "\x00", headers: true }.freeze
|
13
13
|
|
14
|
-
attr_reader :content, :summary
|
14
|
+
attr_reader :content, :summary
|
15
15
|
|
16
16
|
def initialize(res, encoding)
|
17
17
|
super(res)
|
18
|
-
|
19
|
-
|
18
|
+
scrub_body!(encoding)
|
19
|
+
extract_content_and_summary
|
20
20
|
end
|
21
21
|
|
22
22
|
def parse(&blk)
|
23
|
-
CSV.parse(
|
23
|
+
CSV.parse(content, OPTIONS, &blk) if content
|
24
24
|
end
|
25
25
|
|
26
26
|
def records_count
|
27
|
-
summarize if summary
|
27
|
+
summarize if summary
|
28
28
|
end
|
29
29
|
|
30
30
|
def valid?
|
@@ -33,22 +33,13 @@ module Peddler
|
|
33
33
|
|
34
34
|
private
|
35
35
|
|
36
|
-
def
|
37
|
-
|
38
|
-
@summary, @content = body.split("\n\n")
|
39
|
-
else
|
40
|
-
@content = body.dup
|
41
|
-
end
|
36
|
+
def scrub_body!(encoding)
|
37
|
+
body.force_encoding(encoding) unless body.encoding == 'UTF-8'
|
42
38
|
end
|
43
39
|
|
44
|
-
def
|
45
|
-
content
|
46
|
-
|
47
|
-
.encode('UTF-8', invalid: :replace, undef: :replace, replace: '?')
|
48
|
-
end
|
49
|
-
|
50
|
-
def summary?
|
51
|
-
body.include?("\n\n")
|
40
|
+
def extract_content_and_summary
|
41
|
+
@content = body.encode('UTF-8', invalid: :replace, undef: :replace)
|
42
|
+
@summary, @content = @content.split("\n\n") if @content.include?("\n\n")
|
52
43
|
end
|
53
44
|
|
54
45
|
def summarize
|
data/lib/peddler/headers.rb
CHANGED
data/lib/peddler/vcr_matcher.rb
CHANGED
@@ -2,13 +2,13 @@ module Peddler
|
|
2
2
|
# A custom matcher that can be used to record MWS interactions when
|
3
3
|
# integration-testing
|
4
4
|
class VCRMatcher
|
5
|
-
TRANSIENT_PARAMS = %w
|
5
|
+
TRANSIENT_PARAMS = %w[
|
6
6
|
Signature Timestamp StartDate CreatedAfter QueryStartDateTime
|
7
|
-
|
7
|
+
].freeze
|
8
8
|
|
9
|
-
SELLER_PARAMS = %w
|
9
|
+
SELLER_PARAMS = %w[
|
10
10
|
AWSAccessKeyId SellerId
|
11
|
-
|
11
|
+
].freeze
|
12
12
|
|
13
13
|
class << self
|
14
14
|
def call(*requests)
|
data/lib/peddler/version.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -17,19 +17,21 @@ class TestFeeds < IntegrationTest
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def test_submits_feeds
|
20
|
-
|
21
|
-
|
20
|
+
feed_content = "sku\tprice\tquantity\nwidget\t\t0\n"
|
21
|
+
feed_type = '_POST_FLAT_FILE_PRICEANDQUANTITYONLY_UPDATE_DATA_'
|
22
22
|
|
23
23
|
clients.each do |client|
|
24
|
-
res = client.submit_feed(
|
25
|
-
|
26
|
-
|
24
|
+
res = client.submit_feed(feed_content, feed_type)
|
25
|
+
feed_submission_id = res.dig('FeedSubmissionInfo', 'FeedSubmissionId')
|
26
|
+
assert feed_submission_id
|
27
|
+
|
28
|
+
res = client.get_feed_submission_result(feed_submission_id)
|
29
|
+
assert res.records_count
|
27
30
|
|
28
31
|
# Clean up
|
29
|
-
client.body = nil
|
30
32
|
client.cancel_feed_submissions(
|
31
|
-
feed_submission_id:
|
32
|
-
feed_type_list:
|
33
|
+
feed_submission_id: feed_submission_id,
|
34
|
+
feed_type_list: feed_type
|
33
35
|
)
|
34
36
|
end
|
35
37
|
end
|
@@ -37,18 +37,12 @@ class TestReports < IntegrationTest
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
def test_gets_report_list
|
41
|
-
clients.each do |client|
|
42
|
-
res = client.get_report_list
|
43
|
-
refute_empty res.parse
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
40
|
def test_gets_report
|
48
41
|
clients.each do |client|
|
49
42
|
res = client.get_report_list(max_count: 1)
|
50
43
|
id = res.parse['ReportInfo']['ReportId']
|
51
44
|
res = client.get_report(id)
|
45
|
+
assert res.valid?
|
52
46
|
refute_empty res.parse || res.records_count
|
53
47
|
end
|
54
48
|
end
|
data/test/integration_helper.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'helper'
|
2
2
|
require 'recorder'
|
3
3
|
|
4
|
-
%w
|
4
|
+
%w[mws.yml mws.yml.example].each do |path|
|
5
5
|
file = File.expand_path("../#{path}", __FILE__)
|
6
6
|
if File.exist?(file)
|
7
7
|
$mws = YAML.load_file(file)
|
@@ -16,9 +16,7 @@ class IntegrationTest < MiniTest::Test
|
|
16
16
|
|
17
17
|
def clients
|
18
18
|
api = @api || test_name
|
19
|
-
$mws.map
|
20
|
-
MWS.const_get("#{api}::Client").new(record)
|
21
|
-
end
|
19
|
+
$mws.map { |record| MWS.const_get("#{api}::Client").new(record) }.shuffle
|
22
20
|
end
|
23
21
|
end
|
24
22
|
|
@@ -26,9 +24,9 @@ end
|
|
26
24
|
|
27
25
|
VCR.configure do |c|
|
28
26
|
c.before_record do |interaction|
|
29
|
-
%w
|
27
|
+
%w[
|
30
28
|
BuyerName BuyerEmail Name AddressLine1 PostalCode Phone Amount
|
31
|
-
|
29
|
+
].each do |key|
|
32
30
|
interaction.response.body.gsub!(/<#{key}>[^<]+</, "<#{key}>FILTERED<")
|
33
31
|
end
|
34
32
|
end
|
@@ -9,14 +9,26 @@ class TestMWSMerchantFulfillmentClient < MiniTest::Test
|
|
9
9
|
def test_gets_eligible_shipping_services
|
10
10
|
operation = {
|
11
11
|
'Action' => 'GetEligibleShippingServices',
|
12
|
-
'ShipmentRequestDetails.
|
13
|
-
'ShipmentRequestDetails.
|
12
|
+
'ShipmentRequestDetails.AmazonOrderId' => '123',
|
13
|
+
'ShipmentRequestDetails.Weight.Value' => '10',
|
14
|
+
'ShipmentRequestDetails.Weight.Unit' => 'ounces',
|
15
|
+
'ShipmentRequestDetails.ItemList.Item.1.OrderItemId' => '123',
|
16
|
+
'ShipmentRequestDetails.ItemList.Item.1.Quantity' => '1'
|
14
17
|
}
|
15
18
|
|
16
19
|
@client.stub(:run, nil) do
|
17
20
|
shipment_request_details = {
|
18
|
-
|
19
|
-
|
21
|
+
amazon_order_id: '123',
|
22
|
+
weight: {
|
23
|
+
value: '10',
|
24
|
+
unit: 'ounces'
|
25
|
+
},
|
26
|
+
item_list: [
|
27
|
+
{
|
28
|
+
order_item_id: '123',
|
29
|
+
quantity: '1'
|
30
|
+
}
|
31
|
+
]
|
20
32
|
}
|
21
33
|
@client.get_eligible_shipping_services(shipment_request_details)
|
22
34
|
end
|
@@ -27,15 +39,27 @@ class TestMWSMerchantFulfillmentClient < MiniTest::Test
|
|
27
39
|
def test_creates_shipment
|
28
40
|
operation = {
|
29
41
|
'Action' => 'CreateShipment',
|
30
|
-
'ShipmentRequestDetails.
|
31
|
-
'ShipmentRequestDetails.
|
42
|
+
'ShipmentRequestDetails.AmazonOrderId' => '123',
|
43
|
+
'ShipmentRequestDetails.Weight.Value' => '10',
|
44
|
+
'ShipmentRequestDetails.Weight.Unit' => 'ounces',
|
45
|
+
'ShipmentRequestDetails.ItemList.Item.1.OrderItemId' => '123',
|
46
|
+
'ShipmentRequestDetails.ItemList.Item.1.Quantity' => '1',
|
32
47
|
'ShippingServiceId' => 'FOO'
|
33
48
|
}
|
34
49
|
|
35
50
|
@client.stub(:run, nil) do
|
36
51
|
shipment_request_details = {
|
37
|
-
|
38
|
-
|
52
|
+
amazon_order_id: '123',
|
53
|
+
weight: {
|
54
|
+
value: '10',
|
55
|
+
unit: 'ounces'
|
56
|
+
},
|
57
|
+
item_list: [
|
58
|
+
{
|
59
|
+
order_item_id: '123',
|
60
|
+
quantity: '1'
|
61
|
+
}
|
62
|
+
]
|
39
63
|
}
|
40
64
|
@client.create_shipment(shipment_request_details, 'FOO')
|
41
65
|
end
|
@@ -3,9 +3,9 @@ require 'null_client'
|
|
3
3
|
|
4
4
|
class TestPeddlerClient < MiniTest::Test
|
5
5
|
def setup
|
6
|
-
@
|
6
|
+
@response_body = 'foo'
|
7
7
|
Excon.defaults[:mock] = true
|
8
|
-
Excon.stub({}, body: @
|
8
|
+
Excon.stub({}, body: @response_body, status: 200)
|
9
9
|
|
10
10
|
@klass = Class.new(Null::Client)
|
11
11
|
@client = @klass.new
|
@@ -71,14 +71,14 @@ class TestPeddlerClient < MiniTest::Test
|
|
71
71
|
assert_equal '123', client.aws_access_key_id
|
72
72
|
end
|
73
73
|
|
74
|
-
def
|
74
|
+
def test_sets_content_type_header_for_latin_flat_file
|
75
75
|
@client.body = 'foo'
|
76
76
|
content_type = @client.headers.fetch('Content-Type')
|
77
77
|
|
78
78
|
assert_equal 'text/tab-separated-values; charset=CP1252', content_type
|
79
79
|
end
|
80
80
|
|
81
|
-
def
|
81
|
+
def test_sets_content_type_header_for_chinese_flat_file
|
82
82
|
@client.primary_marketplace_id = 'AAHKV2X7AFYLW'
|
83
83
|
@client.body = 'foo'
|
84
84
|
content_type = @client.headers.fetch('Content-Type')
|
@@ -86,7 +86,7 @@ class TestPeddlerClient < MiniTest::Test
|
|
86
86
|
assert_equal 'text/tab-separated-values; charset=UTF-16', content_type
|
87
87
|
end
|
88
88
|
|
89
|
-
def
|
89
|
+
def test_sets_content_type_header_for_japanese_flat_file
|
90
90
|
@client.primary_marketplace_id = 'A1VC38T7YXB528'
|
91
91
|
@client.body = 'foo'
|
92
92
|
content_type = @client.headers.fetch('Content-Type')
|
@@ -94,16 +94,46 @@ class TestPeddlerClient < MiniTest::Test
|
|
94
94
|
assert_equal 'text/tab-separated-values; charset=Windows-31J', content_type
|
95
95
|
end
|
96
96
|
|
97
|
-
def
|
97
|
+
def test_sets_content_type_header_for_xml
|
98
98
|
@client.body = '<?xml version="1.0"?><Foo></Foo>'
|
99
99
|
content_type = @client.headers.fetch('Content-Type')
|
100
100
|
|
101
101
|
assert_equal 'text/xml', content_type
|
102
102
|
end
|
103
103
|
|
104
|
+
def test_encodes_body_for_latin_flat_file
|
105
|
+
@client.body = 'foo'
|
106
|
+
assert_equal 'Windows-1252', @client.body.encoding.to_s
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_encodes_body_for_chinese_flat_file
|
110
|
+
@client.primary_marketplace_id = 'AAHKV2X7AFYLW'
|
111
|
+
@client.body = 'foo'
|
112
|
+
assert_equal 'UTF-16', @client.body.encoding.to_s
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_encodes_body_for_japanese_flat_file
|
116
|
+
@client.primary_marketplace_id = 'A1VC38T7YXB528'
|
117
|
+
@client.body = 'foo'
|
118
|
+
assert_equal 'Windows-31J', @client.body.encoding.to_s
|
119
|
+
end
|
120
|
+
|
104
121
|
def test_runs_a_request
|
105
122
|
res = @client.run
|
106
|
-
assert_equal @
|
123
|
+
assert_equal @response_body, res.body
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_clears_body_when_run_succeeds
|
127
|
+
@client.body = 'foo'
|
128
|
+
@client.run
|
129
|
+
assert_nil @client.body
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_does_not_clear_body_when_run_fails
|
133
|
+
Excon.stub({}, status: 503)
|
134
|
+
@client.body = 'foo'
|
135
|
+
assert_raises { @client.run }
|
136
|
+
refute_nil @client.body
|
107
137
|
end
|
108
138
|
|
109
139
|
def test_streams_response
|
@@ -111,7 +141,7 @@ class TestPeddlerClient < MiniTest::Test
|
|
111
141
|
streamer = ->(chunk, _, _) { chunks << chunk }
|
112
142
|
@client.run(&streamer)
|
113
143
|
|
114
|
-
assert_equal @
|
144
|
+
assert_equal @response_body, chunks
|
115
145
|
end
|
116
146
|
|
117
147
|
class Instrumentor
|
@@ -70,7 +70,7 @@ class TestPeddlerFlatFileParser < MiniTest::Test
|
|
70
70
|
body = "Foo\n\xFF\n"
|
71
71
|
body.force_encoding('ASCII-8BIT')
|
72
72
|
parser = Peddler::FlatFileParser.new(build_mock_response(body), 'ASCII-8BIT')
|
73
|
-
assert_equal '
|
73
|
+
assert_equal '�', parser.parse['Foo'][0]
|
74
74
|
end
|
75
75
|
|
76
76
|
private
|
@@ -15,10 +15,10 @@ class TestPeddlerOperation < MiniTest::Test
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def test_converts_nested_key_to_structured_list
|
18
|
-
@operation.store('Foo.Status', [1])
|
18
|
+
@operation.store('Foo.Status', [{ 'Baz' => 1 }])
|
19
19
|
@operation.structure!('Status', 'Bar')
|
20
20
|
refute @operation.key?('FooStatus')
|
21
|
-
assert_equal 1, @operation['Foo.Status.Bar.1']
|
21
|
+
assert_equal 1, @operation['Foo.Status.Bar.1.Baz']
|
22
22
|
end
|
23
23
|
|
24
24
|
def test_store_camelizes_symbol_key
|
@@ -13,12 +13,12 @@ class TestPeddlerStructuredList < MiniTest::Test
|
|
13
13
|
|
14
14
|
def test_builds_a_structured_list_for_an_array_of_values
|
15
15
|
exp = { 'OrderStatus.Status.1' => 'foo', 'OrderStatus.Status.2' => 'bar' }
|
16
|
-
assert_equal exp, @list.build(%w
|
16
|
+
assert_equal exp, @list.build(%w[foo bar])
|
17
17
|
end
|
18
18
|
|
19
19
|
def test_flattens_nested_arrays_of_values
|
20
20
|
exp = { 'OrderStatus.Status.1' => 'foo', 'OrderStatus.Status.2' => 'bar' }
|
21
|
-
assert_equal exp, @list.build([%w
|
21
|
+
assert_equal exp, @list.build([%w[foo bar]])
|
22
22
|
end
|
23
23
|
|
24
24
|
def test_handles_single_key
|
@@ -31,7 +31,7 @@ class TestPeddlerXMLResponseParser < MiniTest::Test
|
|
31
31
|
def response(body)
|
32
32
|
OpenStruct.new(
|
33
33
|
body: body,
|
34
|
-
headers: { 'Content-Type' => 'text/xml', 'Content-Length' =>
|
34
|
+
headers: { 'Content-Type' => 'text/xml', 'Content-Length' => body.size }
|
35
35
|
)
|
36
36
|
end
|
37
37
|
end
|