Skip to content

Commit 6f68ac0

Browse files
authored
fix: correctly deserialize restjson error code (#865)
* fix: correctly deserialize restjson error code (#828) * Fixed change log format and restjson error code deserialization * Fixed bug and added unit tests * Added extra unit test * Removed redundant code * Simplified code/Removed duplicate lines
1 parent 87dd1c2 commit 6f68ac0

File tree

3 files changed

+74
-13
lines changed

3 files changed

+74
-13
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"id": "c641c1f7-0758-49d2-8dbd-e375853143c7",
3+
"type": "bugfix",
4+
"description": "Use correct precedence order for determining restJson error codes",
5+
"issues": [
6+
"awslabs/smithy-kotlin#828"
7+
]
8+
}

runtime/protocol/aws-json-protocols/common/src/aws/smithy/kotlin/runtime/awsprotocol/json/RestJsonErrorDeserializer.kt

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,17 @@ public object RestJsonErrorDeserializer {
4646
}
4747

4848
public fun deserialize(headers: Headers, payload: ByteArray?): ErrorDetails {
49-
var code: String? = headers[X_AMZN_ERROR_TYPE_HEADER_NAME]
50-
var message: String? = headers[X_AMZN_ERROR_MESSAGE_HEADER_NAME]
51-
if (message == null) {
52-
message = headers[X_AMZN_EVENT_ERROR_MESSAGE_HEADER_NAME]
53-
}
49+
var message = headers[X_AMZN_ERROR_MESSAGE_HEADER_NAME] ?: headers[X_AMZN_EVENT_ERROR_MESSAGE_HEADER_NAME]
50+
val headerCode: String? = headers[X_AMZN_ERROR_TYPE_HEADER_NAME]
51+
var bodyCode: String? = null
52+
var bodyType: String? = null
5453

5554
if (payload != null) {
56-
val deserializer = JsonDeserializer(payload)
57-
deserializer.deserializeStruct(OBJ_DESCRIPTOR) {
58-
loop@while (true) {
55+
JsonDeserializer(payload).deserializeStruct(OBJ_DESCRIPTOR) {
56+
loop@ while (true) {
5957
when (findNextFieldIndex()) {
60-
ERR_CODE_ALT1_DESCRIPTOR.index,
61-
ERR_CODE_ALT2_DESCRIPTOR.index,
62-
-> code = deserializeString()
58+
ERR_CODE_ALT1_DESCRIPTOR.index -> bodyCode = deserializeString()
59+
ERR_CODE_ALT2_DESCRIPTOR.index -> bodyType = deserializeString()
6360
MESSAGE_ALT1_DESCRIPTOR.index,
6461
MESSAGE_ALT2_DESCRIPTOR.index,
6562
MESSAGE_ALT3_DESCRIPTOR.index,
@@ -70,8 +67,16 @@ public object RestJsonErrorDeserializer {
7067
}
7168
}
7269
}
73-
74-
return ErrorDetails(sanitize(code), message, requestId = null)
70+
/**
71+
* According to the spec we should check the following locations in order:
72+
*
73+
* HTTP header x-amzn-errortype
74+
* top-level body field code
75+
* top-level body field __type
76+
*
77+
* Source: https://github.com/awslabs/aws-sdk-kotlin/issues/828
78+
*/
79+
return ErrorDetails(sanitize(headerCode ?: bodyCode ?: bodyType), message, requestId = null)
7580
}
7681
}
7782

runtime/protocol/aws-json-protocols/common/test/aws/smithy/kotlin/runtime/awsprotocol/json/RestJsonErrorDeserializerTest.kt

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,54 @@ class RestJsonErrorDeserializerTest {
6464
}
6565
}
6666

67+
@OptIn(ExperimentalStdlibApi::class, ExperimentalCoroutinesApi::class)
68+
@Test
69+
fun `it deserializes aws restJson error codes using right location check order`() = runTest {
70+
// Checking for header code return
71+
var headers = Headers {
72+
append(X_AMZN_ERROR_TYPE_HEADER_NAME, "HeaderCode")
73+
}
74+
var payload = """
75+
{
76+
"code": "BodyCode",
77+
"__type": "TypeCode"
78+
}
79+
""".trimIndent().encodeToByteArray()
80+
assertEquals("HeaderCode", RestJsonErrorDeserializer.deserialize(headers, payload).code)
81+
82+
payload = """
83+
{
84+
"__type": "TypeCode"
85+
}
86+
""".trimIndent().encodeToByteArray()
87+
assertEquals("HeaderCode", RestJsonErrorDeserializer.deserialize(headers, payload).code)
88+
89+
payload = """
90+
{
91+
"code": "BodyCode"
92+
}
93+
""".trimIndent().encodeToByteArray()
94+
assertEquals("HeaderCode", RestJsonErrorDeserializer.deserialize(headers, payload).code)
95+
96+
// Checking for body code return
97+
headers = Headers {}
98+
payload = """
99+
{
100+
"code": "BodyCode",
101+
"__type": "TypeCode"
102+
}
103+
""".trimIndent().encodeToByteArray()
104+
assertEquals("BodyCode", RestJsonErrorDeserializer.deserialize(headers, payload).code)
105+
106+
payload = """
107+
{
108+
"__type": "TypeCode",
109+
"code": "BodyCode"
110+
}
111+
""".trimIndent().encodeToByteArray()
112+
assertEquals("BodyCode", RestJsonErrorDeserializer.deserialize(headers, payload).code)
113+
}
114+
67115
@OptIn(ExperimentalStdlibApi::class, ExperimentalCoroutinesApi::class)
68116
@Test
69117
fun `it deserializes aws restJson error messages`() = runTest {

0 commit comments

Comments
 (0)