Skip to content

Commit 6e23175

Browse files
authored
Default empty array for previously flattened lists and maps in query compatible services (#2948)
1 parent 6273072 commit 6e23175

File tree

5 files changed

+96
-115
lines changed

5 files changed

+96
-115
lines changed

gems/aws-sdk-core/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
Unreleased Changes
22
------------------
33

4+
* Issue - For `awsQueryCompatible` services, default an empty list or map for shapes that were previously flattened in the query protocol.
5+
46
3.187.0 (2023-11-17)
57
------------------
68

gems/aws-sdk-core/lib/aws-sdk-core/json/handler.rb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,10 @@ def parse_body(context)
5959
end
6060
resp_struct
6161
else
62-
Parser.new(rules).parse(json == '' ? '{}' : json)
62+
Parser.new(
63+
rules,
64+
query_compatible: query_compatible?(context)
65+
).parse(json == '' ? '{}' : json)
6366
end
6467
else
6568
EmptyStructure.new
@@ -83,6 +86,10 @@ def simple_json?(context)
8386
context.config.simple_json
8487
end
8588

89+
def query_compatible?(context)
90+
context.config.api.metadata.key?('awsQueryCompatible')
91+
end
92+
8693
end
8794
end
8895
end

gems/aws-sdk-core/lib/aws-sdk-core/json/parser.rb

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ class Parser
1010
include Seahorse::Model::Shapes
1111

1212
# @param [Seahorse::Model::ShapeRef] rules
13-
def initialize(rules)
13+
def initialize(rules, query_compatible: false)
1414
@rules = rules
15+
@query_compatible = query_compatible
1516
end
1617

1718
# @param [String<JSON>] json
@@ -32,6 +33,22 @@ def structure(ref, values, target = nil)
3233
target[:unknown] = { 'name' => key, 'value' => value }
3334
end
3435
end
36+
# In services that were previously Query/XML, members that were
37+
# "flattened" defaulted to empty lists. In JSON, these values are nil,
38+
# which is backwards incompatible. To preserve backwards compatibility,
39+
# we set a default value of [] for these members.
40+
if @query_compatible
41+
ref.shape.members.each do |member_name, member_target|
42+
next unless target[member_name].nil?
43+
44+
if flattened_list?(member_target.shape)
45+
target[member_name] = []
46+
elsif flattened_map?(member_target.shape)
47+
target[member_name] = {}
48+
end
49+
end
50+
end
51+
3552
if shape.union
3653
# convert to subclass
3754
member_subclass = shape.member_subclass(target.member).new
@@ -79,6 +96,14 @@ def time(value)
7996
value.is_a?(Numeric) ? Time.at(value) : Time.parse(value)
8097
end
8198

99+
def flattened_list?(shape)
100+
shape.is_a?(ListShape) && shape.flattened
101+
end
102+
103+
def flattened_map?(shape)
104+
shape.is_a?(MapShape) && shape.flattened
105+
end
106+
82107
end
83108
end
84109
end

gems/aws-sdk-sqs/spec/client/verify_checksums_spec.rb

Lines changed: 38 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -54,25 +54,13 @@ class Client
5454
let(:md5_of_attributes) { '756d7f4338696745d063b420a2f7e502' }
5555

5656
before(:each) do
57-
if client.config.api.metadata['protocol'] == 'json'
58-
response_body = <<-JSON
59-
{
60-
"MD5OfMessageAttributes": "#{md5_of_attributes}",
61-
"MD5OfMessageBody": "900150983cd24fb0d6963f7d28e17f72",
62-
"MessageId": "5fea7756-0ea4-451a-a703-a558b933e274"
63-
}
64-
JSON
65-
else
66-
response_body = <<-XML
67-
<SendMessageResponse>
68-
<SendMessageResult>
69-
<MD5OfMessageBody>900150983cd24fb0d6963f7d28e17f72</MD5OfMessageBody>
70-
<MD5OfMessageAttributes>#{md5_of_attributes}</MD5OfMessageAttributes>
71-
<MessageId>5fea7756-0ea4-451a-a703-a558b933e274</MessageId>
72-
</SendMessageResult>
73-
</SendMessageResponse>
74-
XML
75-
end
57+
response_body = <<-JSON
58+
{
59+
"MD5OfMessageAttributes": "#{md5_of_attributes}",
60+
"MD5OfMessageBody": "900150983cd24fb0d6963f7d28e17f72",
61+
"MessageId": "5fea7756-0ea4-451a-a703-a558b933e274"
62+
}
63+
JSON
7664

7765
client.handle(step: :send) do |context|
7866
context.http_response.signal_done(
@@ -167,42 +155,22 @@ class Client
167155
describe '#send_message_batch' do
168156

169157
before(:each) do
170-
if client.config.api.metadata['protocol'] == 'json'
171-
client.handle(step: :send) do |context|
172-
context.http_response.signal_done(
173-
status_code: 200,
174-
headers: {},
175-
body:<<-JSON)
176-
{
177-
"Successful": [
178-
{
179-
"Id": "msg-id",
180-
"MD5OfMessageBody": "900150983cd24fb0d6963f7d28e17f72",
181-
"MD5OfMessageAttributes": "756d7f4338696745d063b420a2f7e502"
182-
}
183-
]
184-
}
185-
JSON
186-
Seahorse::Client::Response.new(context: context)
187-
end
188-
else
189-
client.handle(step: :send) do |context|
190-
context.http_response.signal_done(
191-
status_code: 200,
192-
headers: {},
193-
body:<<-XML)
194-
<SendMessageBatchResponse>
195-
<SendMessageBatchResult>
196-
<SendMessageBatchResultEntry>
197-
<Id>msg-id</Id>
198-
<MD5OfMessageBody>900150983cd24fb0d6963f7d28e17f72</MD5OfMessageBody>
199-
<MD5OfMessageAttributes>756d7f4338696745d063b420a2f7e502</MD5OfMessageAttributes>
200-
</SendMessageBatchResultEntry>
201-
</SendMessageBatchResult>
202-
</SendMessageBatchResponse>
203-
XML
204-
Seahorse::Client::Response.new(context: context)
205-
end
158+
client.handle(step: :send) do |context|
159+
context.http_response.signal_done(
160+
status_code: 200,
161+
headers: {},
162+
body:<<-JSON)
163+
{
164+
"Successful": [
165+
{
166+
"Id": "msg-id",
167+
"MD5OfMessageBody": "900150983cd24fb0d6963f7d28e17f72",
168+
"MD5OfMessageAttributes": "756d7f4338696745d063b420a2f7e502"
169+
}
170+
]
171+
}
172+
JSON
173+
Seahorse::Client::Response.new(context: context)
206174
end
207175
end
208176

@@ -253,39 +221,21 @@ class Client
253221
end
254222

255223
it 'skips failed errors' do
256-
if client.config.api.metadata['protocol'] == 'json'
257-
client.handle(step: :send) do |context|
258-
context.http_response.signal_done(
259-
status_code: 200,
260-
headers: {},
261-
body:<<-JSON)
262-
{
263-
"Successful": [],
264-
"Failed": [
265-
{
266-
"Id": "msg-id"
267-
}
268-
]
269-
}
270-
JSON
271-
Seahorse::Client::Response.new(context: context)
272-
end
273-
else
274-
client.handle(step: :send) do |context|
275-
context.http_response.signal_done(
276-
status_code: 200,
277-
headers: {},
278-
body:<<-XML)
279-
<SendMessageBatchResponse>
280-
<SendMessageBatchResult>
281-
<BatchResultErrorEntry>
282-
<Id>msg-id</Id>
283-
</BatchResultErrorEntry>
284-
</SendMessageBatchResult>
285-
</SendMessageBatchResponse>
286-
XML
287-
Seahorse::Client::Response.new(context: context)
288-
end
224+
client.handle(step: :send) do |context|
225+
context.http_response.signal_done(
226+
status_code: 200,
227+
headers: {},
228+
body:<<-JSON)
229+
{
230+
"Successful": [],
231+
"Failed": [
232+
{
233+
"Id": "msg-id"
234+
}
235+
]
236+
}
237+
JSON
238+
Seahorse::Client::Response.new(context: context)
289239
end
290240
expect {
291241
client.send_message_batch(

gems/aws-sdk-sqs/spec/client_spec.rb

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,36 +21,33 @@ module SQS
2121
end
2222

2323
describe 'empty result element' do
24-
it 'returns a structure with all of the root members' do
25-
if client.config.api.metadata['protocol'] == 'json'
26-
client.handle(step: :send) do |context|
27-
context.http_response.signal_done(
28-
status_code: 200,
29-
headers: {},
30-
body: '{"Messages": []}'
31-
)
32-
Seahorse::Client::Response.new(context: context)
33-
end
34-
else
35-
client.handle(step: :send) do |context|
36-
context.http_response.signal_done(
37-
status_code: 200,
38-
headers: {},
39-
body:<<-XML)
40-
<ReceiveMessageResponse>
41-
<ReceiveMessageResult/>
42-
<ResponseMetadata>
43-
<RequestId>request-id</RequestId>
44-
</ResponseMetadata>
45-
</ReceiveMessageResponse>
46-
XML
47-
Seahorse::Client::Response.new(context: context)
48-
end
24+
it 'defaults to an empty list' do
25+
client.handle(step: :send) do |context|
26+
context.http_response.signal_done(
27+
status_code: 200,
28+
headers: {},
29+
body: '{}'
30+
)
31+
Seahorse::Client::Response.new(context: context)
4932
end
5033
resp = client.receive_message(queue_url: 'https://foo.com')
5134
expect(resp.data.members).to eq([:messages])
5235
expect(resp.data.messages).to eq([])
5336
end
37+
38+
it 'defaults to an empty map' do
39+
client.handle(step: :send) do |context|
40+
context.http_response.signal_done(
41+
status_code: 200,
42+
headers: {},
43+
body: '{}'
44+
)
45+
Seahorse::Client::Response.new(context: context)
46+
end
47+
resp = client.list_queue_tags(queue_url: 'https://foo.com')
48+
expect(resp.data.members).to eq([:tags])
49+
expect(resp.data.tags).to eq({})
50+
end
5451
end
5552

5653
describe '#stub_responses' do

0 commit comments

Comments
 (0)