From a9443a427b957d62d055756a36e11ceb199111bd Mon Sep 17 00:00:00 2001 From: Aaron J Todd Date: Fri, 23 Feb 2024 14:02:50 -0500 Subject: [PATCH 01/11] refactor xml protocol deserialization --- .../s3/UnwrappedXmlOutputIntegration.kt | 15 +-- .../s3/UnwrappedXmlOutputIntegrationTest.kt | 30 ----- .../kotlin/codegen/aws/protocols/AwsQuery.kt | 119 +++++++++--------- .../kotlin/codegen/aws/protocols/Ec2Query.kt | 97 +++++++++----- .../kotlin/codegen/aws/protocols/RestXml.kt | 104 ++++++++++++++- gradle/libs.versions.toml | 4 +- 6 files changed, 244 insertions(+), 125 deletions(-) delete mode 100644 codegen/aws-sdk-codegen/src/test/kotlin/aws/sdk/kotlin/codegen/customization/s3/UnwrappedXmlOutputIntegrationTest.kt diff --git a/codegen/aws-sdk-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/customization/s3/UnwrappedXmlOutputIntegration.kt b/codegen/aws-sdk-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/customization/s3/UnwrappedXmlOutputIntegration.kt index d51f70624f0..42cca196eb6 100644 --- a/codegen/aws-sdk-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/customization/s3/UnwrappedXmlOutputIntegration.kt +++ b/codegen/aws-sdk-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/customization/s3/UnwrappedXmlOutputIntegration.kt @@ -11,31 +11,32 @@ import software.amazon.smithy.kotlin.codegen.model.expectShape import software.amazon.smithy.kotlin.codegen.model.hasTrait import software.amazon.smithy.kotlin.codegen.model.traits.UnwrappedXmlOutput import software.amazon.smithy.model.Model +import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.model.shapes.ServiceShape -import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.model.transform.ModelTransformer /** - * Applies the [UnwrappedXmlOutput] custom-made [annotation trait](https://smithy.io/2.0/spec/model.html?highlight=annotation#annotation-traits) to structures - * whose operation is annotated with `S3UnwrappedXmlOutput` trait to mark when special unwrapped xml output deserialization is required. + * Applies the custom [UnwrappedXmlOutput] + * [annotation trait](https://smithy.io/2.0/spec/model.html?highlight=annotation#annotation-traits) to operations + * annotated with `S3UnwrappedXmlOutput` trait to mark when special unwrapped xml output deserialization is required. */ class UnwrappedXmlOutputIntegration : KotlinIntegration { override fun enabledForService(model: Model, settings: KotlinSettings): Boolean = model.expectShape(settings.service).isS3 override fun preprocessModel(model: Model, settings: KotlinSettings): Model { - val unwrappedStructures = model + val unwrappedOperations = model .operationShapes .filter { it.hasTrait() } - .map { it.outputShape } + .map { it.id } .toSet() return ModelTransformer .create() .mapShapes(model) { shape -> when { - shape.id in unwrappedStructures -> - (shape as StructureShape).toBuilder().addTrait(UnwrappedXmlOutput()).build() + shape.id in unwrappedOperations -> + (shape as OperationShape).toBuilder().addTrait(UnwrappedXmlOutput()).build() else -> shape } } diff --git a/codegen/aws-sdk-codegen/src/test/kotlin/aws/sdk/kotlin/codegen/customization/s3/UnwrappedXmlOutputIntegrationTest.kt b/codegen/aws-sdk-codegen/src/test/kotlin/aws/sdk/kotlin/codegen/customization/s3/UnwrappedXmlOutputIntegrationTest.kt deleted file mode 100644 index 7827fed4915..00000000000 --- a/codegen/aws-sdk-codegen/src/test/kotlin/aws/sdk/kotlin/codegen/customization/s3/UnwrappedXmlOutputIntegrationTest.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ -package aws.sdk.kotlin.codegen.customization.s3 - -import aws.sdk.kotlin.codegen.testutil.model -import org.junit.jupiter.api.Assertions.assertFalse -import org.junit.jupiter.api.Test -import software.amazon.smithy.kotlin.codegen.test.defaultSettings -import kotlin.test.assertTrue - -/** - * Verify [UnwrappedXmlOutputIntegration] is enabled for proper service (S3) - */ -class UnwrappedXmlOutputIntegrationTest { - @Test - fun testNonS3Model() { - val model = model("NotS3") - val actual = UnwrappedXmlOutputIntegration().enabledForService(model, model.defaultSettings()) - assertFalse(actual) - } - - @Test - fun testS3Model() { - val model = model("S3") - val actual = UnwrappedXmlOutputIntegration().enabledForService(model, model.defaultSettings()) - assertTrue(actual) - } -} diff --git a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/AwsQuery.kt b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/AwsQuery.kt index 5aed86cb8c2..4ed06644ca2 100644 --- a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/AwsQuery.kt +++ b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/AwsQuery.kt @@ -12,11 +12,10 @@ import software.amazon.smithy.kotlin.codegen.aws.protocols.core.AwsHttpBindingPr import software.amazon.smithy.kotlin.codegen.aws.protocols.core.QueryHttpBindingProtocolGenerator import software.amazon.smithy.kotlin.codegen.aws.protocols.formurl.QuerySerdeFormUrlDescriptorGenerator import software.amazon.smithy.kotlin.codegen.core.* +import software.amazon.smithy.kotlin.codegen.lang.KotlinTypes import software.amazon.smithy.kotlin.codegen.model.* -import software.amazon.smithy.kotlin.codegen.model.traits.OperationOutput import software.amazon.smithy.kotlin.codegen.rendering.protocol.* import software.amazon.smithy.kotlin.codegen.rendering.serde.* -import software.amazon.smithy.kotlin.codegen.utils.dq import software.amazon.smithy.model.shapes.* import software.amazon.smithy.model.traits.* @@ -68,24 +67,6 @@ private class AwsQuerySerdeFormUrlDescriptorGenerator( member.hasTrait() } -private class AwsQuerySerdeXmlDescriptorGenerator( - ctx: RenderingContext, - memberShapes: List? = null, -) : XmlSerdeDescriptorGenerator(ctx, memberShapes) { - - override fun getObjectDescriptorTraits(): List { - val traits = super.getObjectDescriptorTraits().toMutableList() - - if (objectShape.hasTrait()) { - traits.removeIf { it.symbol == RuntimeTypes.Serde.SerdeXml.XmlSerialName } - val serialName = objectShape.changeNameSuffix("Response" to "Result") - traits.add(RuntimeTypes.Serde.SerdeXml.XmlSerialName, serialName.dq()) - } - - return traits - } -} - private class AwsQuerySerializerGenerator( private val protocolGenerator: AwsQuery, ) : AbstractQueryFormUrlSerializerGenerator(protocolGenerator, protocolGenerator.defaultTimestampFormat) { @@ -98,50 +79,76 @@ private class AwsQuerySerializerGenerator( } private class AwsQueryXmlParserGenerator( - private val protocolGenerator: AwsQuery, + protocolGenerator: AwsQuery, ) : XmlParserGenerator(protocolGenerator, protocolGenerator.defaultTimestampFormat) { - override fun descriptorGenerator( - ctx: ProtocolGenerator.GenerationContext, - shape: Shape, - members: List, - writer: KotlinWriter, - ): XmlSerdeDescriptorGenerator = AwsQuerySerdeXmlDescriptorGenerator(ctx.toRenderingContext(protocolGenerator, shape, writer), members) - - override fun renderDeserializeOperationBody( - ctx: ProtocolGenerator.GenerationContext, - op: OperationShape, - documentMembers: List, - writer: KotlinWriter, - ) { - writer.write("val deserializer = #T(payload)", RuntimeTypes.Serde.SerdeXml.XmlDeserializer) - unwrapOperationResponseBody(op.id.name, writer) - val shape = ctx.model.expectShape(op.output.get()) - renderDeserializerBody(ctx, shape, documentMembers, writer) - } - /** * Unwraps the response body as specified by * https://awslabs.github.io/smithy/1.0/spec/aws/aws-query-protocol.html#response-serialization so that the * deserializer is in the correct state. + * + * ``` + * + * + * <-- SAME AS REST XML --> + * + * + * ``` */ - private fun unwrapOperationResponseBody( - operationName: String, + override fun unwrapOperationBody( + ctx: ProtocolGenerator.GenerationContext, + serdeCtx: SerdeCtx, + op: OperationShape, writer: KotlinWriter, - ) { - writer.write("// begin unwrap response wrapper") - .write("val resultDescriptor = #T(#T.Struct, #T(#S))", RuntimeTypes.Serde.SdkFieldDescriptor, RuntimeTypes.Serde.SerialKind, RuntimeTypes.Serde.SerdeXml.XmlSerialName, "${operationName}Result") - .withBlock("val wrapperDescriptor = #T.build {", "}", RuntimeTypes.Serde.SdkObjectDescriptor) { - write("trait(#T(#S))", RuntimeTypes.Serde.SerdeXml.XmlSerialName, "${operationName}Response") - write("#T(resultDescriptor)", RuntimeTypes.Serde.field) + ): SerdeCtx { + val operationName = op.id.getName(ctx.service) + + val unwrapAwsQueryOperation = buildSymbol { + name = "unwrapAwsQueryResponse" + namespace = ctx.settings.pkg.serde + definitionFile = "AwsQueryUtil.kt" + renderBy = { writer -> + + writer.withBlock( + "internal fun $name(root: #1T, operationName: #2T): #1T {", + "}", + RuntimeTypes.Serde.SerdeXml.TagReader, + KotlinTypes.String, + ) { + write("val responseWrapperName = \"\${operationName}Response\"") + write("val resultWrapperName = \"\${operationName}Result\"") + withBlock( + "if (root.startTag.name.tag != responseWrapperName) {", + "}", + ) { + write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid root, expected \$responseWrapperName; found `\${root.startTag}`") + } + + write("val resultTag = ${serdeCtx.tagReader}.nextTag()") + withBlock( + "if (resultTag == null || resultTag.startTag.name.tag != resultWrapperName) {", + "}", + ) { + write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid result, expected \$resultWrapperName; found `\${resultTag?.startTag}`") + } + + write("return resultTag") + } } - .write("") - // abandon the iterator, this only occurs at the top level operational output - .write("val wrapper = deserializer.#T(wrapperDescriptor)", RuntimeTypes.Serde.deserializeStruct) - .withBlock("if (wrapper.findNextFieldIndex() != resultDescriptor.index) {", "}") { - write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "failed to unwrap $operationName response") - } - .write("// end unwrap response wrapper") - .write("") + } + + writer.write("val unwrapped = #T(#L, #S)", unwrapAwsQueryOperation, serdeCtx.tagReader, operationName) + + return SerdeCtx("unwrapped") + } + + override fun unwrapOperationError( + ctx: ProtocolGenerator.GenerationContext, + serdeCtx: SerdeCtx, + errorShape: StructureShape, + writer: KotlinWriter, + ): SerdeCtx { + writer.write("val errReader = #T(${serdeCtx.tagReader})", RestXmlErrors.wrappedErrorResponseDeserializer(ctx)) + return SerdeCtx("errReader") } } diff --git a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/Ec2Query.kt b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/Ec2Query.kt index 3db60123682..a3168646a31 100644 --- a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/Ec2Query.kt +++ b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/Ec2Query.kt @@ -6,20 +6,19 @@ package software.amazon.smithy.kotlin.codegen.aws.protocols import software.amazon.smithy.aws.traits.protocols.Ec2QueryNameTrait import software.amazon.smithy.aws.traits.protocols.Ec2QueryTrait +import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.kotlin.codegen.aws.protocols.core.AbstractQueryFormUrlSerializerGenerator import software.amazon.smithy.kotlin.codegen.aws.protocols.core.QueryHttpBindingProtocolGenerator import software.amazon.smithy.kotlin.codegen.aws.protocols.formurl.QuerySerdeFormUrlDescriptorGenerator import software.amazon.smithy.kotlin.codegen.core.KotlinWriter import software.amazon.smithy.kotlin.codegen.core.RenderingContext import software.amazon.smithy.kotlin.codegen.core.RuntimeTypes -import software.amazon.smithy.kotlin.codegen.model.changeNameSuffix +import software.amazon.smithy.kotlin.codegen.core.withBlock +import software.amazon.smithy.kotlin.codegen.model.buildSymbol import software.amazon.smithy.kotlin.codegen.model.getTrait -import software.amazon.smithy.kotlin.codegen.model.hasTrait -import software.amazon.smithy.kotlin.codegen.model.traits.OperationOutput import software.amazon.smithy.kotlin.codegen.rendering.protocol.ProtocolGenerator import software.amazon.smithy.kotlin.codegen.rendering.protocol.toRenderingContext import software.amazon.smithy.kotlin.codegen.rendering.serde.* -import software.amazon.smithy.kotlin.codegen.utils.dq import software.amazon.smithy.model.shapes.* import software.amazon.smithy.model.traits.XmlNameTrait @@ -73,24 +72,6 @@ private class Ec2QuerySerdeFormUrlDescriptorGenerator( targetShape.type == ShapeType.LIST } -private class Ec2QuerySerdeXmlDescriptorGenerator( - ctx: RenderingContext, - memberShapes: List? = null, -) : XmlSerdeDescriptorGenerator(ctx, memberShapes) { - - override fun getObjectDescriptorTraits(): List { - val traits = super.getObjectDescriptorTraits().toMutableList() - - if (objectShape.hasTrait()) { - traits.removeIf { it.symbol == RuntimeTypes.Serde.SerdeXml.XmlSerialName } - val serialName = objectShape.changeNameSuffix("Response" to "Result") - traits.add(RuntimeTypes.Serde.SerdeXml.XmlSerialName, serialName.dq()) - } - - return traits - } -} - private class Ec2QuerySerializerGenerator( private val protocolGenerator: Ec2Query, ) : AbstractQueryFormUrlSerializerGenerator(protocolGenerator, protocolGenerator.defaultTimestampFormat) { @@ -104,13 +85,73 @@ private class Ec2QuerySerializerGenerator( } private class Ec2QueryParserGenerator( - private val protocolGenerator: Ec2Query, + protocolGenerator: Ec2Query, ) : XmlParserGenerator(protocolGenerator, protocolGenerator.defaultTimestampFormat) { - - override fun descriptorGenerator( + override fun unwrapOperationError( ctx: ProtocolGenerator.GenerationContext, - shape: Shape, - members: List, + serdeCtx: SerdeCtx, + errorShape: StructureShape, writer: KotlinWriter, - ): XmlSerdeDescriptorGenerator = Ec2QuerySerdeXmlDescriptorGenerator(ctx.toRenderingContext(protocolGenerator, shape, writer), members) + ): SerdeCtx { + val unwrapFn = unwrapErrorResponse(ctx) + writer.write("val errReader = #T(${serdeCtx.tagReader})", unwrapFn) + return SerdeCtx("errReader") + } + + /** + * Error deserializer for a wrapped error response + * + * ``` + * + * + * + * <-- DATA -->> + * + * + * + * ``` + * + * See https://smithy.io/2.0/aws/protocols/aws-ec2-query-protocol.html#operation-error-serialization + */ + private fun unwrapErrorResponse(ctx: ProtocolGenerator.GenerationContext): Symbol = buildSymbol { + name = "unwrapXmlErrorResponse" + namespace = ctx.settings.pkg.serde + definitionFile = "XmlErrorUtils.kt" + renderBy = { writer -> + writer.dokka("Handle [wrapped](https://smithy.io/2.0/aws/protocols/aws-ec2-query-protocol.html#operation-error-serialization) error responses") + writer.withBlock( + "internal fun $name(root: #1T): #1T {", + "}", + RuntimeTypes.Serde.SerdeXml.TagReader, + ) { + withBlock( + "if (root.startTag.name.tag != #S) {", + "}", + "Response", + ) { + write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid root, expected ; found `\${root.startTag}`") + } + + write("val errorsTag = root.nextTag()") + withBlock( + "if (errorsTag == null || errorsTag.startTag.name.tag != #S) {", + "}", + "Errors", + ) { + write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid error, expected ; found `\${errorsTag?.startTag}`") + } + + write("val errTag = errorsTag.nextTag()") + withBlock( + "if (errTag == null || errTag.startTag.name.tag != #S) {", + "}", + "Error", + ) { + write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid error, expected ; found `\${errTag?.startTag}`") + } + + write("return errTag") + } + } + } } diff --git a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt index 158fc9c0262..36df309aefd 100644 --- a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt +++ b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt @@ -90,6 +90,7 @@ class RestXmlParserGenerator( else -> super.payloadDeserializer(ctx, shape, members) } + // FIXME - reconcile private fun explicitBoundStructureDeserializer( ctx: ProtocolGenerator.GenerationContext, boundMember: MemberShape, @@ -112,14 +113,113 @@ class RestXmlParserGenerator( addNestedDocumentDeserializers(ctx, targetShape, writer) writer.dokka("Payload deserializer for ${memberSymbol.name} with a different XML name trait (${xmlNameTrait.value})") writer.withBlock("internal fun $name(payload: ByteArray): #T {", "}", memberSymbol) { - write("val deserializer = #T(payload)", RuntimeTypes.Serde.SerdeXml.XmlDeserializer) + writer.write("val root = #T(payload).#T()", RuntimeTypes.Serde.SerdeXml.xmlStreamReader, RuntimeTypes.Serde.SerdeXml.root) + val serdeCtx = SerdeCtx("root") write("val builder = #T.Builder()", memberSymbol) - renderDeserializerBody(ctx, copyWithMemberTraits, targetShape.members().toList(), writer) + renderDeserializerBody(ctx, serdeCtx, copyWithMemberTraits, targetShape.members().toList(), writer) write("return builder.build()") } } } } + + override fun unwrapOperationError( + ctx: ProtocolGenerator.GenerationContext, + serdeCtx: SerdeCtx, + errorShape: StructureShape, + writer: KotlinWriter, + ): SerdeCtx { + val unwrapFn = when (ctx.service.getTrait()?.isNoErrorWrapping == true) { + true -> RestXmlErrors.unwrappedErrorResponseDeserializer(ctx) + false -> RestXmlErrors.wrappedErrorResponseDeserializer(ctx) + } + writer.write("val errReader = #T(${serdeCtx.tagReader})", unwrapFn) + return SerdeCtx("errReader") + } +} + +object RestXmlErrors { + + /** + * Error deserializer for a wrapped error response + * + * ``` + * + * + * <-- DATA -->> + * + * + * ``` + * + * See https://smithy.io/2.0/aws/protocols/aws-restxml-protocol.html#error-response-serialization + */ + fun wrappedErrorResponseDeserializer(ctx: ProtocolGenerator.GenerationContext): Symbol = buildSymbol { + name = "unwrapWrappedXmlErrorResponse" + namespace = ctx.settings.pkg.serde + definitionFile = "XmlErrorUtils.kt" + renderBy = { writer -> + writer.dokka("Handle [wrapped](https://smithy.io/2.0/aws/protocols/aws-restxml-protocol.html#error-response-serialization) error responses") + writer.withBlock( + "internal fun $name(root: #1T): #1T {", + "}", + RuntimeTypes.Serde.SerdeXml.TagReader, + ) { + withBlock( + "if (root.startTag.name.tag != #S) {", + "}", + "ErrorResponse", + ) { + write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid root, expected ; found `\${root.startTag}`") + } + + write("val errTag = root.nextTag()") + withBlock( + "if (errTag == null || errTag.startTag.name.tag != #S) {", + "}", + "Error", + ) { + write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid error, expected ; found `\${errTag?.startTag}`") + } + + write("return errTag") + } + } + } + + /** + * Error deserializer for an unwrapped error response + * + * ``` + * + * <-- DATA -->> + * + * ``` + * + * See https://smithy.io/2.0/aws/protocols/aws-restxml-protocol.html#error-response-serialization + */ + fun unwrappedErrorResponseDeserializer(ctx: ProtocolGenerator.GenerationContext): Symbol = buildSymbol { + name = "unwrapXmlErrorResponse" + namespace = ctx.settings.pkg.serde + definitionFile = "XmlErrorUtils.kt" + renderBy = { writer -> + writer.dokka("Handle [unwrapped](https://smithy.io/2.0/aws/protocols/aws-restxml-protocol.html#error-response-serialization) error responses (restXml.noErrorWrapping == true)") + writer.withBlock( + "internal fun $name(root: #1T): #1T {", + "}", + RuntimeTypes.Serde.SerdeXml.TagReader, + ) { + withBlock( + "if (root.startTag.name.tag != #S) {", + "}", + "Error", + ) { + write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid error, expected ; found `\${errTag?.startTag}`") + } + + write("return root") + } + } + } } class RestXmlSerializerGenerator( diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 063cd76d368..88a30d55c61 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,8 +9,8 @@ coroutines-version = "1.7.3" atomicfu-version = "0.23.1" # smithy-kotlin codegen and runtime are versioned separately -smithy-kotlin-runtime-version = "1.0.15" -smithy-kotlin-codegen-version = "0.30.16" +smithy-kotlin-runtime-version = "1.0.16-SNAPSHOT" +smithy-kotlin-codegen-version = "0.30.17-SNAPSHOT" # codegen smithy-version = "1.42.0" From 614d0a64298c5e650fd260083116cb5490355cce Mon Sep 17 00:00:00 2001 From: Aaron J Todd Date: Fri, 23 Feb 2024 14:54:00 -0500 Subject: [PATCH 02/11] fix error deserializer --- .../amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt index 36df309aefd..7b8190a4fb6 100644 --- a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt +++ b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt @@ -213,7 +213,7 @@ object RestXmlErrors { "}", "Error", ) { - write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid error, expected ; found `\${errTag?.startTag}`") + write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid error, expected ; found `\${root.startTag}`") } write("return root") @@ -245,6 +245,7 @@ class RestXmlSerializerGenerator( else -> super.payloadSerializer(ctx, shape, members) } + // FIXME private fun explicitBoundStructureSerializer( ctx: ProtocolGenerator.GenerationContext, boundMember: MemberShape, From 406d43f34969b7f2e4ba67b82de5a14c55428aaf Mon Sep 17 00:00:00 2001 From: Aaron J Todd Date: Sat, 24 Feb 2024 21:15:51 -0500 Subject: [PATCH 03/11] fix custom deserializers --- .../ChangeResourceRecordSetsUnmarshalling.kt | 62 +++++++++---------- ...angeResourceRecordSetsUnmarshallingTest.kt | 2 +- .../services/s3/internal/S3ErrorMetadata.kt | 36 ++++------- 3 files changed, 43 insertions(+), 57 deletions(-) diff --git a/services/route53/common/src/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshalling.kt b/services/route53/common/src/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshalling.kt index 5b5af0d4748..e75a0e7dd6f 100644 --- a/services/route53/common/src/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshalling.kt +++ b/services/route53/common/src/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshalling.kt @@ -6,50 +6,48 @@ package aws.sdk.kotlin.services.route53.internal import aws.sdk.kotlin.services.route53.model.InvalidChangeBatch import aws.smithy.kotlin.runtime.awsprotocol.ErrorDetails -import aws.smithy.kotlin.runtime.serde.* +import aws.smithy.kotlin.runtime.awsprotocol.xml.parseRestXmlErrorResponse import aws.smithy.kotlin.runtime.serde.xml.* internal fun parseRestXmlInvalidChangeBatchResponse(payload: ByteArray): InvalidChangeBatchErrorResponse? = deserializeInvalidChangeBatchError(InvalidChangeBatch.Builder(), payload) internal fun deserializeInvalidChangeBatchError(builder: InvalidChangeBatch.Builder, payload: ByteArray): InvalidChangeBatchErrorResponse? { - val deserializer = XmlDeserializer(payload) - val MESSAGE_DESCRIPTOR = SdkFieldDescriptor(SerialKind.String, XmlSerialName("message"), XmlAliasName("Message")) - val MESSAGES_DESCRIPTOR = SdkFieldDescriptor(SerialKind.List, XmlSerialName("messages"), XmlAliasName("Messages"), XmlCollectionName("Message")) - val REQUESTID_DESCRIPTOR = SdkFieldDescriptor(SerialKind.String, XmlSerialName("RequestId")) - val OBJ_DESCRIPTOR = SdkObjectDescriptor.build { - trait(XmlSerialName("InvalidChangeBatch")) - trait(XmlNamespace("https://route53.amazonaws.com/doc/2013-04-01/")) - field(MESSAGE_DESCRIPTOR) - field(MESSAGES_DESCRIPTOR) - field(REQUESTID_DESCRIPTOR) + val root = xmlStreamReader(payload).root() + if (root.startTag.name.tag == "ErrorResponse") { + val errDetails = parseRestXmlErrorResponse(payload) + builder.message = errDetails.message + return InvalidChangeBatchErrorResponse(errDetails, builder.build()) } + var requestId: String? = null - return try { - deserializer.deserializeStruct(OBJ_DESCRIPTOR) { - loop@while (true) { - when (findNextFieldIndex()) { - MESSAGE_DESCRIPTOR.index -> builder.message = deserializeString() - REQUESTID_DESCRIPTOR.index -> requestId = deserializeString() - MESSAGES_DESCRIPTOR.index -> - builder.messages = deserializer.deserializeList(MESSAGES_DESCRIPTOR) { - val col0 = mutableListOf() - while (hasNextElement()) { - val el0 = if (nextHasValue()) { deserializeString() } else { deserializeNull(); continue } - col0.add(el0) - } - col0 - } - null -> break@loop - else -> skipValue() - } + loop@while (true) { + val curr = root.nextTag() ?: break@loop + when (curr.startTag.name.tag) { + "Message", "message" -> builder.message = curr.data() + "Messages", "messages" -> builder.messages = deserializeMessages(curr) + "RequestId" -> requestId = curr.data() + } + curr.drop() + } + + return InvalidChangeBatchErrorResponse(ErrorDetails("InvalidChangeBatch", builder.message, requestId), builder.build()) +} + +private fun deserializeMessages(root: TagReader): List { + val result = mutableListOf() + loop@while (true) { + val curr = root.nextTag() ?: break@loop + when (curr.startTag.name.tag) { + "Message" -> { + val el = curr.tryData().getOrNull() ?: continue@loop + result.add(el) } } - InvalidChangeBatchErrorResponse(ErrorDetails("InvalidChangeBatch", builder.message, requestId), builder.build()) - } catch (e: DeserializationException) { - null // return so an appropriate exception type can be instantiated above here. } + + return result } internal data class InvalidChangeBatchErrorResponse( diff --git a/services/route53/common/test/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshallingTest.kt b/services/route53/common/test/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshallingTest.kt index b6bd664a3d3..de99fd13630 100644 --- a/services/route53/common/test/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshallingTest.kt +++ b/services/route53/common/test/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshallingTest.kt @@ -32,7 +32,7 @@ class ChangeResourceRecordSetsUnmarshallingTest { """.trimIndent() - val response: HttpResponse = HttpResponse( + val response = HttpResponse( HttpStatusCode.BadRequest, Headers.Empty, HttpBody.fromBytes(bodyText.encodeToByteArray()), diff --git a/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/S3ErrorMetadata.kt b/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/S3ErrorMetadata.kt index 68ad4342281..4bec30f39ac 100644 --- a/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/S3ErrorMetadata.kt +++ b/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/S3ErrorMetadata.kt @@ -14,8 +14,9 @@ import aws.smithy.kotlin.runtime.awsprotocol.setAseErrorMetadata import aws.smithy.kotlin.runtime.collections.setIfValueNotNull import aws.smithy.kotlin.runtime.http.response.HttpResponse import aws.smithy.kotlin.runtime.serde.* -import aws.smithy.kotlin.runtime.serde.xml.XmlDeserializer -import aws.smithy.kotlin.runtime.serde.xml.XmlSerialName +import aws.smithy.kotlin.runtime.serde.xml.data +import aws.smithy.kotlin.runtime.serde.xml.root +import aws.smithy.kotlin.runtime.serde.xml.xmlStreamReader /** * Default header name identifying secondary request ID @@ -45,35 +46,22 @@ internal fun setS3ErrorMetadata(exception: Any, response: HttpResponse, errorDet } internal fun parseS3ErrorResponse(payload: ByteArray): S3ErrorDetails { - val MESSAGE_DESCRIPTOR = SdkFieldDescriptor(SerialKind.String, XmlSerialName("Message")) - val CODE_DESCRIPTOR = SdkFieldDescriptor(SerialKind.String, XmlSerialName("Code")) - val REQUESTID_DESCRIPTOR = SdkFieldDescriptor(SerialKind.String, XmlSerialName("RequestId")) - val HOSTID_DESCRIPTOR = SdkFieldDescriptor(SerialKind.String, XmlSerialName("HostId")) - val OBJ_DESCRIPTOR = SdkObjectDescriptor.build { - trait(XmlSerialName("Error")) - field(MESSAGE_DESCRIPTOR) - field(CODE_DESCRIPTOR) - field(REQUESTID_DESCRIPTOR) - field(HOSTID_DESCRIPTOR) - } + val root = xmlStreamReader(payload).root() var message: String? = null var code: String? = null var requestId: String? = null var requestId2: String? = null - val deserializer = XmlDeserializer(payload, true) - deserializer.deserializeStruct(OBJ_DESCRIPTOR) { - loop@ while (true) { - when (findNextFieldIndex()) { - MESSAGE_DESCRIPTOR.index -> message = deserializeString() - CODE_DESCRIPTOR.index -> code = deserializeString() - REQUESTID_DESCRIPTOR.index -> requestId = deserializeString() - HOSTID_DESCRIPTOR.index -> requestId2 = deserializeString() - null -> break@loop - else -> skipValue() - } + loop@ while (true) { + val curr = root.nextTag() ?: break@loop + when (curr.startTag.name.tag) { + "Code" -> code = curr.data() + "Message", "message" -> message = curr.data() + "RequestId" -> requestId = curr.data() + "HostId" -> requestId2 = curr.data() } + curr.drop() } return S3ErrorDetails(code, message, requestId, requestId2) From 437846dc18b7fa90fd73026d16b99babbb37c636 Mon Sep 17 00:00:00 2001 From: Aaron J Todd Date: Sat, 24 Feb 2024 21:24:43 -0500 Subject: [PATCH 04/11] remove unused --- .../kotlin/codegen/aws/protocols/AwsQuery.kt | 2 +- .../kotlin/codegen/aws/protocols/Ec2Query.kt | 2 +- .../smithy/kotlin/codegen/aws/protocols/RestXml.kt | 14 +++----------- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/AwsQuery.kt b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/AwsQuery.kt index 4ed06644ca2..5606696d7a9 100644 --- a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/AwsQuery.kt +++ b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/AwsQuery.kt @@ -80,7 +80,7 @@ private class AwsQuerySerializerGenerator( private class AwsQueryXmlParserGenerator( protocolGenerator: AwsQuery, -) : XmlParserGenerator(protocolGenerator, protocolGenerator.defaultTimestampFormat) { +) : XmlParserGenerator(protocolGenerator.defaultTimestampFormat) { /** * Unwraps the response body as specified by diff --git a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/Ec2Query.kt b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/Ec2Query.kt index a3168646a31..aa7dab7d932 100644 --- a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/Ec2Query.kt +++ b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/Ec2Query.kt @@ -86,7 +86,7 @@ private class Ec2QuerySerializerGenerator( private class Ec2QueryParserGenerator( protocolGenerator: Ec2Query, -) : XmlParserGenerator(protocolGenerator, protocolGenerator.defaultTimestampFormat) { +) : XmlParserGenerator(protocolGenerator.defaultTimestampFormat) { override fun unwrapOperationError( ctx: ProtocolGenerator.GenerationContext, serdeCtx: SerdeCtx, diff --git a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt index 7b8190a4fb6..5db443c5cbd 100644 --- a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt +++ b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt @@ -52,7 +52,7 @@ open class RestXml : AwsHttpBindingProtocolGenerator() { } override fun structuredDataParser(ctx: ProtocolGenerator.GenerationContext): StructuredDataParserGenerator = - RestXmlParserGenerator(this, defaultTimestampFormat) + RestXmlParserGenerator(this) override fun structuredDataSerializer(ctx: ProtocolGenerator.GenerationContext): StructuredDataSerializerGenerator = RestXmlSerializerGenerator(this, defaultTimestampFormat) @@ -68,16 +68,8 @@ open class RestXml : AwsHttpBindingProtocolGenerator() { } class RestXmlParserGenerator( - private val protocolGenerator: RestXml, - defaultTimestampFormat: TimestampFormatTrait.Format, -) : XmlParserGenerator(protocolGenerator, defaultTimestampFormat) { - - override fun descriptorGenerator( - ctx: ProtocolGenerator.GenerationContext, - shape: Shape, - members: List, - writer: KotlinWriter, - ): XmlSerdeDescriptorGenerator = RestXmlSerdeDescriptorGenerator(ctx.toRenderingContext(protocolGenerator, shape, writer), members) + protocolGenerator: RestXml, +) : XmlParserGenerator(protocolGenerator.defaultTimestampFormat) { override fun payloadDeserializer( ctx: ProtocolGenerator.GenerationContext, From 5e39c2f1c05b71e7117e7c90be0f4d44458d4476 Mon Sep 17 00:00:00 2001 From: Aaron J Todd Date: Sat, 24 Feb 2024 22:31:45 -0500 Subject: [PATCH 05/11] upstream cleanup --- .../kotlin/codegen/aws/protocols/AwsQuery.kt | 8 ++++---- .../kotlin/codegen/aws/protocols/Ec2Query.kt | 12 ++++++------ .../smithy/kotlin/codegen/aws/protocols/RestXml.kt | 14 +++++++------- .../ChangeResourceRecordSetsUnmarshalling.kt | 8 ++++---- .../kotlin/services/s3/internal/S3ErrorMetadata.kt | 9 +++------ 5 files changed, 24 insertions(+), 27 deletions(-) diff --git a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/AwsQuery.kt b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/AwsQuery.kt index 5606696d7a9..620a1eae03e 100644 --- a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/AwsQuery.kt +++ b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/AwsQuery.kt @@ -118,18 +118,18 @@ private class AwsQueryXmlParserGenerator( write("val responseWrapperName = \"\${operationName}Response\"") write("val resultWrapperName = \"\${operationName}Result\"") withBlock( - "if (root.startTag.name.tag != responseWrapperName) {", + "if (root.tag.name.tag != responseWrapperName) {", "}", ) { - write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid root, expected \$responseWrapperName; found `\${root.startTag}`") + write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid root, expected \$responseWrapperName; found `\${root.tag}`") } write("val resultTag = ${serdeCtx.tagReader}.nextTag()") withBlock( - "if (resultTag == null || resultTag.startTag.name.tag != resultWrapperName) {", + "if (resultTag == null || resultTag.tag.name.tag != resultWrapperName) {", "}", ) { - write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid result, expected \$resultWrapperName; found `\${resultTag?.startTag}`") + write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid result, expected \$resultWrapperName; found `\${resultTag?.tag}`") } write("return resultTag") diff --git a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/Ec2Query.kt b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/Ec2Query.kt index aa7dab7d932..9bb0e5a45c1 100644 --- a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/Ec2Query.kt +++ b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/Ec2Query.kt @@ -125,29 +125,29 @@ private class Ec2QueryParserGenerator( RuntimeTypes.Serde.SerdeXml.TagReader, ) { withBlock( - "if (root.startTag.name.tag != #S) {", + "if (root.tag.name.tag != #S) {", "}", "Response", ) { - write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid root, expected ; found `\${root.startTag}`") + write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid root, expected ; found `\${root.tag}`") } write("val errorsTag = root.nextTag()") withBlock( - "if (errorsTag == null || errorsTag.startTag.name.tag != #S) {", + "if (errorsTag == null || errorsTag.tag.name.tag != #S) {", "}", "Errors", ) { - write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid error, expected ; found `\${errorsTag?.startTag}`") + write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid error, expected ; found `\${errorsTag?.tag}`") } write("val errTag = errorsTag.nextTag()") withBlock( - "if (errTag == null || errTag.startTag.name.tag != #S) {", + "if (errTag == null || errTag.tag.name.tag != #S) {", "}", "Error", ) { - write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid error, expected ; found `\${errTag?.startTag}`") + write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid error, expected ; found `\${errTag?.tag}`") } write("return errTag") diff --git a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt index 5db443c5cbd..96397d75622 100644 --- a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt +++ b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt @@ -105,7 +105,7 @@ class RestXmlParserGenerator( addNestedDocumentDeserializers(ctx, targetShape, writer) writer.dokka("Payload deserializer for ${memberSymbol.name} with a different XML name trait (${xmlNameTrait.value})") writer.withBlock("internal fun $name(payload: ByteArray): #T {", "}", memberSymbol) { - writer.write("val root = #T(payload).#T()", RuntimeTypes.Serde.SerdeXml.xmlStreamReader, RuntimeTypes.Serde.SerdeXml.root) + writer.write("val root = #T(payload)", RuntimeTypes.Serde.SerdeXml.xmlTagReader) val serdeCtx = SerdeCtx("root") write("val builder = #T.Builder()", memberSymbol) renderDeserializerBody(ctx, serdeCtx, copyWithMemberTraits, targetShape.members().toList(), writer) @@ -157,20 +157,20 @@ object RestXmlErrors { RuntimeTypes.Serde.SerdeXml.TagReader, ) { withBlock( - "if (root.startTag.name.tag != #S) {", + "if (root.tag.name.tag != #S) {", "}", "ErrorResponse", ) { - write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid root, expected ; found `\${root.startTag}`") + write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid root, expected ; found `\${root.tag}`") } write("val errTag = root.nextTag()") withBlock( - "if (errTag == null || errTag.startTag.name.tag != #S) {", + "if (errTag == null || errTag.tag.name.tag != #S) {", "}", "Error", ) { - write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid error, expected ; found `\${errTag?.startTag}`") + write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid error, expected ; found `\${errTag?.tag}`") } write("return errTag") @@ -201,11 +201,11 @@ object RestXmlErrors { RuntimeTypes.Serde.SerdeXml.TagReader, ) { withBlock( - "if (root.startTag.name.tag != #S) {", + "if (root.tag.name.tag != #S) {", "}", "Error", ) { - write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid error, expected ; found `\${root.startTag}`") + write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid error, expected ; found `\${root.tag}`") } write("return root") diff --git a/services/route53/common/src/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshalling.kt b/services/route53/common/src/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshalling.kt index e75a0e7dd6f..32d929445c9 100644 --- a/services/route53/common/src/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshalling.kt +++ b/services/route53/common/src/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshalling.kt @@ -14,7 +14,7 @@ internal fun parseRestXmlInvalidChangeBatchResponse(payload: ByteArray): Invalid internal fun deserializeInvalidChangeBatchError(builder: InvalidChangeBatch.Builder, payload: ByteArray): InvalidChangeBatchErrorResponse? { val root = xmlStreamReader(payload).root() - if (root.startTag.name.tag == "ErrorResponse") { + if (root.tag.name.tag == "ErrorResponse") { val errDetails = parseRestXmlErrorResponse(payload) builder.message = errDetails.message return InvalidChangeBatchErrorResponse(errDetails, builder.build()) @@ -24,7 +24,7 @@ internal fun deserializeInvalidChangeBatchError(builder: InvalidChangeBatch.Buil loop@while (true) { val curr = root.nextTag() ?: break@loop - when (curr.startTag.name.tag) { + when (curr.tag.name.tag) { "Message", "message" -> builder.message = curr.data() "Messages", "messages" -> builder.messages = deserializeMessages(curr) "RequestId" -> requestId = curr.data() @@ -35,11 +35,11 @@ internal fun deserializeInvalidChangeBatchError(builder: InvalidChangeBatch.Buil return InvalidChangeBatchErrorResponse(ErrorDetails("InvalidChangeBatch", builder.message, requestId), builder.build()) } -private fun deserializeMessages(root: TagReader): List { +private fun deserializeMessages(root: XmlTagReader): List { val result = mutableListOf() loop@while (true) { val curr = root.nextTag() ?: break@loop - when (curr.startTag.name.tag) { + when (curr.tag.name.tag) { "Message" -> { val el = curr.tryData().getOrNull() ?: continue@loop result.add(el) diff --git a/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/S3ErrorMetadata.kt b/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/S3ErrorMetadata.kt index 4bec30f39ac..2a2db6fad87 100644 --- a/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/S3ErrorMetadata.kt +++ b/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/S3ErrorMetadata.kt @@ -5,7 +5,6 @@ package aws.sdk.kotlin.services.s3.internal import aws.sdk.kotlin.runtime.AwsServiceException -import aws.sdk.kotlin.runtime.http.* import aws.sdk.kotlin.services.s3.model.S3ErrorMetadata import aws.sdk.kotlin.services.s3.model.S3Exception import aws.smithy.kotlin.runtime.ServiceErrorMetadata @@ -13,10 +12,8 @@ import aws.smithy.kotlin.runtime.awsprotocol.AwsErrorDetails import aws.smithy.kotlin.runtime.awsprotocol.setAseErrorMetadata import aws.smithy.kotlin.runtime.collections.setIfValueNotNull import aws.smithy.kotlin.runtime.http.response.HttpResponse -import aws.smithy.kotlin.runtime.serde.* import aws.smithy.kotlin.runtime.serde.xml.data -import aws.smithy.kotlin.runtime.serde.xml.root -import aws.smithy.kotlin.runtime.serde.xml.xmlStreamReader +import aws.smithy.kotlin.runtime.serde.xml.xmlTagReader /** * Default header name identifying secondary request ID @@ -46,7 +43,7 @@ internal fun setS3ErrorMetadata(exception: Any, response: HttpResponse, errorDet } internal fun parseS3ErrorResponse(payload: ByteArray): S3ErrorDetails { - val root = xmlStreamReader(payload).root() + val root = xmlTagReader(payload) var message: String? = null var code: String? = null @@ -55,7 +52,7 @@ internal fun parseS3ErrorResponse(payload: ByteArray): S3ErrorDetails { loop@ while (true) { val curr = root.nextTag() ?: break@loop - when (curr.startTag.name.tag) { + when (curr.tag.name.tag) { "Code" -> code = curr.data() "Message", "message" -> message = curr.data() "RequestId" -> requestId = curr.data() From 04e0a44c7a9eb1ae0e59b2616fd15ad0fd4e3ca1 Mon Sep 17 00:00:00 2001 From: Aaron J Todd Date: Sat, 24 Feb 2024 23:15:06 -0500 Subject: [PATCH 06/11] more upstream cleanup --- .../smithy/kotlin/codegen/aws/protocols/AwsQuery.kt | 6 +++--- .../smithy/kotlin/codegen/aws/protocols/Ec2Query.kt | 8 ++++---- .../smithy/kotlin/codegen/aws/protocols/RestXml.kt | 12 ++++++------ .../ChangeResourceRecordSetsUnmarshalling.kt | 8 ++++---- .../s3/internal/Handle200ErrorsInterceptor.kt | 2 +- .../kotlin/services/s3/internal/S3ErrorMetadata.kt | 2 +- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/AwsQuery.kt b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/AwsQuery.kt index 620a1eae03e..841a04c937a 100644 --- a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/AwsQuery.kt +++ b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/AwsQuery.kt @@ -112,13 +112,13 @@ private class AwsQueryXmlParserGenerator( writer.withBlock( "internal fun $name(root: #1T, operationName: #2T): #1T {", "}", - RuntimeTypes.Serde.SerdeXml.TagReader, + RuntimeTypes.Serde.SerdeXml.XmlTagReader, KotlinTypes.String, ) { write("val responseWrapperName = \"\${operationName}Response\"") write("val resultWrapperName = \"\${operationName}Result\"") withBlock( - "if (root.tag.name.tag != responseWrapperName) {", + "if (root.tag.name != responseWrapperName) {", "}", ) { write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid root, expected \$responseWrapperName; found `\${root.tag}`") @@ -126,7 +126,7 @@ private class AwsQueryXmlParserGenerator( write("val resultTag = ${serdeCtx.tagReader}.nextTag()") withBlock( - "if (resultTag == null || resultTag.tag.name.tag != resultWrapperName) {", + "if (resultTag == null || resultTag.tag.name != resultWrapperName) {", "}", ) { write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid result, expected \$resultWrapperName; found `\${resultTag?.tag}`") diff --git a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/Ec2Query.kt b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/Ec2Query.kt index 9bb0e5a45c1..ec17ca24423 100644 --- a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/Ec2Query.kt +++ b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/Ec2Query.kt @@ -122,10 +122,10 @@ private class Ec2QueryParserGenerator( writer.withBlock( "internal fun $name(root: #1T): #1T {", "}", - RuntimeTypes.Serde.SerdeXml.TagReader, + RuntimeTypes.Serde.SerdeXml.XmlTagReader, ) { withBlock( - "if (root.tag.name.tag != #S) {", + "if (root.tag.name != #S) {", "}", "Response", ) { @@ -134,7 +134,7 @@ private class Ec2QueryParserGenerator( write("val errorsTag = root.nextTag()") withBlock( - "if (errorsTag == null || errorsTag.tag.name.tag != #S) {", + "if (errorsTag == null || errorsTag.tag.name != #S) {", "}", "Errors", ) { @@ -143,7 +143,7 @@ private class Ec2QueryParserGenerator( write("val errTag = errorsTag.nextTag()") withBlock( - "if (errTag == null || errTag.tag.name.tag != #S) {", + "if (errTag == null || errTag.tag.name != #S) {", "}", "Error", ) { diff --git a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt index 96397d75622..03fc1a57419 100644 --- a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt +++ b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt @@ -105,7 +105,7 @@ class RestXmlParserGenerator( addNestedDocumentDeserializers(ctx, targetShape, writer) writer.dokka("Payload deserializer for ${memberSymbol.name} with a different XML name trait (${xmlNameTrait.value})") writer.withBlock("internal fun $name(payload: ByteArray): #T {", "}", memberSymbol) { - writer.write("val root = #T(payload)", RuntimeTypes.Serde.SerdeXml.xmlTagReader) + writer.write("val root = #T(payload)", RuntimeTypes.Serde.SerdeXml.xmlRootTagReader) val serdeCtx = SerdeCtx("root") write("val builder = #T.Builder()", memberSymbol) renderDeserializerBody(ctx, serdeCtx, copyWithMemberTraits, targetShape.members().toList(), writer) @@ -154,10 +154,10 @@ object RestXmlErrors { writer.withBlock( "internal fun $name(root: #1T): #1T {", "}", - RuntimeTypes.Serde.SerdeXml.TagReader, + RuntimeTypes.Serde.SerdeXml.XmlTagReader, ) { withBlock( - "if (root.tag.name.tag != #S) {", + "if (root.tag.name != #S) {", "}", "ErrorResponse", ) { @@ -166,7 +166,7 @@ object RestXmlErrors { write("val errTag = root.nextTag()") withBlock( - "if (errTag == null || errTag.tag.name.tag != #S) {", + "if (errTag == null || errTag.tag.name != #S) {", "}", "Error", ) { @@ -198,10 +198,10 @@ object RestXmlErrors { writer.withBlock( "internal fun $name(root: #1T): #1T {", "}", - RuntimeTypes.Serde.SerdeXml.TagReader, + RuntimeTypes.Serde.SerdeXml.XmlTagReader, ) { withBlock( - "if (root.tag.name.tag != #S) {", + "if (root.tag.name != #S) {", "}", "Error", ) { diff --git a/services/route53/common/src/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshalling.kt b/services/route53/common/src/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshalling.kt index 32d929445c9..4d240e353e9 100644 --- a/services/route53/common/src/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshalling.kt +++ b/services/route53/common/src/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshalling.kt @@ -13,8 +13,8 @@ internal fun parseRestXmlInvalidChangeBatchResponse(payload: ByteArray): Invalid deserializeInvalidChangeBatchError(InvalidChangeBatch.Builder(), payload) internal fun deserializeInvalidChangeBatchError(builder: InvalidChangeBatch.Builder, payload: ByteArray): InvalidChangeBatchErrorResponse? { - val root = xmlStreamReader(payload).root() - if (root.tag.name.tag == "ErrorResponse") { + val root = xmlTagReader(payload) + if (root.tag.name == "ErrorResponse") { val errDetails = parseRestXmlErrorResponse(payload) builder.message = errDetails.message return InvalidChangeBatchErrorResponse(errDetails, builder.build()) @@ -24,7 +24,7 @@ internal fun deserializeInvalidChangeBatchError(builder: InvalidChangeBatch.Buil loop@while (true) { val curr = root.nextTag() ?: break@loop - when (curr.tag.name.tag) { + when (curr.tag.name) { "Message", "message" -> builder.message = curr.data() "Messages", "messages" -> builder.messages = deserializeMessages(curr) "RequestId" -> requestId = curr.data() @@ -39,7 +39,7 @@ private fun deserializeMessages(root: XmlTagReader): List { val result = mutableListOf() loop@while (true) { val curr = root.nextTag() ?: break@loop - when (curr.tag.name.tag) { + when (curr.tag.name) { "Message" -> { val el = curr.tryData().getOrNull() ?: continue@loop result.add(el) diff --git a/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/Handle200ErrorsInterceptor.kt b/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/Handle200ErrorsInterceptor.kt index c5fe16baeda..aafdf1718e5 100644 --- a/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/Handle200ErrorsInterceptor.kt +++ b/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/Handle200ErrorsInterceptor.kt @@ -32,7 +32,7 @@ internal object Handle200ErrorsInterceptor : HttpInterceptor { // according to the knowledge center article above we should treat these as 5xx, // our retry policy will handle standard error codes like `SlowDown` val statusCode = HttpStatusCode.InternalServerError - .takeIf { token?.name?.local == "Error" } + .takeIf { token?.qualifiedName?.local == "Error" } ?: response.status return response.copy(status = statusCode, body = HttpBody.fromBytes(payload)) } diff --git a/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/S3ErrorMetadata.kt b/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/S3ErrorMetadata.kt index 2a2db6fad87..6f5cb7fef85 100644 --- a/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/S3ErrorMetadata.kt +++ b/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/S3ErrorMetadata.kt @@ -52,7 +52,7 @@ internal fun parseS3ErrorResponse(payload: ByteArray): S3ErrorDetails { loop@ while (true) { val curr = root.nextTag() ?: break@loop - when (curr.tag.name.tag) { + when (curr.tag.name) { "Code" -> code = curr.data() "Message", "message" -> message = curr.data() "RequestId" -> requestId = curr.data() From 79d42ba59bcd8b53f036103705305a9242b54ce9 Mon Sep 17 00:00:00 2001 From: Aaron J Todd Date: Mon, 26 Feb 2024 08:20:35 -0500 Subject: [PATCH 07/11] changelog --- .changes/119ee420-38a5-4974-922e-29cb11de02d0.json | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .changes/119ee420-38a5-4974-922e-29cb11de02d0.json diff --git a/.changes/119ee420-38a5-4974-922e-29cb11de02d0.json b/.changes/119ee420-38a5-4974-922e-29cb11de02d0.json new file mode 100644 index 00000000000..6b02874fee1 --- /dev/null +++ b/.changes/119ee420-38a5-4974-922e-29cb11de02d0.json @@ -0,0 +1,8 @@ +{ + "id": "119ee420-38a5-4974-922e-29cb11de02d0", + "type": "bugfix", + "description": "Refactor XML deserialization to handle flat collections", + "issues": [ + "awslabs/aws-sdk-kotlin#1220" + ] +} \ No newline at end of file From 3d96773d402355892d6fb9253d5947567287dbe6 Mon Sep 17 00:00:00 2001 From: Aaron J Todd Date: Tue, 27 Feb 2024 12:33:46 -0500 Subject: [PATCH 08/11] upstream changes --- .../kotlin/codegen/aws/protocols/AwsQuery.kt | 4 +-- .../kotlin/codegen/aws/protocols/Ec2Query.kt | 6 ++-- .../kotlin/codegen/aws/protocols/RestXml.kt | 6 ++-- .../ChangeResourceRecordSetsUnmarshalling.kt | 11 ++----- ...angeResourceRecordSetsUnmarshallingTest.kt | 31 ------------------- .../s3/internal/Handle200ErrorsInterceptor.kt | 2 +- .../services/s3/internal/S3ErrorMetadata.kt | 2 +- 7 files changed, 12 insertions(+), 50 deletions(-) diff --git a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/AwsQuery.kt b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/AwsQuery.kt index 841a04c937a..027e9050f30 100644 --- a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/AwsQuery.kt +++ b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/AwsQuery.kt @@ -118,7 +118,7 @@ private class AwsQueryXmlParserGenerator( write("val responseWrapperName = \"\${operationName}Response\"") write("val resultWrapperName = \"\${operationName}Result\"") withBlock( - "if (root.tag.name != responseWrapperName) {", + "if (root.tagName != responseWrapperName) {", "}", ) { write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid root, expected \$responseWrapperName; found `\${root.tag}`") @@ -126,7 +126,7 @@ private class AwsQueryXmlParserGenerator( write("val resultTag = ${serdeCtx.tagReader}.nextTag()") withBlock( - "if (resultTag == null || resultTag.tag.name != resultWrapperName) {", + "if (resultTag == null || resultTag.tagName != resultWrapperName) {", "}", ) { write("throw #T(#S)", RuntimeTypes.Serde.DeserializationException, "invalid result, expected \$resultWrapperName; found `\${resultTag?.tag}`") diff --git a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/Ec2Query.kt b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/Ec2Query.kt index ec17ca24423..65751cefad6 100644 --- a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/Ec2Query.kt +++ b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/Ec2Query.kt @@ -125,7 +125,7 @@ private class Ec2QueryParserGenerator( RuntimeTypes.Serde.SerdeXml.XmlTagReader, ) { withBlock( - "if (root.tag.name != #S) {", + "if (root.tagName != #S) {", "}", "Response", ) { @@ -134,7 +134,7 @@ private class Ec2QueryParserGenerator( write("val errorsTag = root.nextTag()") withBlock( - "if (errorsTag == null || errorsTag.tag.name != #S) {", + "if (errorsTag == null || errorsTag.tagName != #S) {", "}", "Errors", ) { @@ -143,7 +143,7 @@ private class Ec2QueryParserGenerator( write("val errTag = errorsTag.nextTag()") withBlock( - "if (errTag == null || errTag.tag.name != #S) {", + "if (errTag == null || errTag.tagName != #S) {", "}", "Error", ) { diff --git a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt index 03fc1a57419..27eada3b0ad 100644 --- a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt +++ b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt @@ -157,7 +157,7 @@ object RestXmlErrors { RuntimeTypes.Serde.SerdeXml.XmlTagReader, ) { withBlock( - "if (root.tag.name != #S) {", + "if (root.tagName != #S) {", "}", "ErrorResponse", ) { @@ -166,7 +166,7 @@ object RestXmlErrors { write("val errTag = root.nextTag()") withBlock( - "if (errTag == null || errTag.tag.name != #S) {", + "if (errTag == null || errTag.tagName != #S) {", "}", "Error", ) { @@ -201,7 +201,7 @@ object RestXmlErrors { RuntimeTypes.Serde.SerdeXml.XmlTagReader, ) { withBlock( - "if (root.tag.name != #S) {", + "if (root.tagName != #S) {", "}", "Error", ) { diff --git a/services/route53/common/src/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshalling.kt b/services/route53/common/src/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshalling.kt index 4d240e353e9..e61e2a62021 100644 --- a/services/route53/common/src/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshalling.kt +++ b/services/route53/common/src/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshalling.kt @@ -6,7 +6,6 @@ package aws.sdk.kotlin.services.route53.internal import aws.sdk.kotlin.services.route53.model.InvalidChangeBatch import aws.smithy.kotlin.runtime.awsprotocol.ErrorDetails -import aws.smithy.kotlin.runtime.awsprotocol.xml.parseRestXmlErrorResponse import aws.smithy.kotlin.runtime.serde.xml.* internal fun parseRestXmlInvalidChangeBatchResponse(payload: ByteArray): InvalidChangeBatchErrorResponse? = @@ -14,17 +13,11 @@ internal fun parseRestXmlInvalidChangeBatchResponse(payload: ByteArray): Invalid internal fun deserializeInvalidChangeBatchError(builder: InvalidChangeBatch.Builder, payload: ByteArray): InvalidChangeBatchErrorResponse? { val root = xmlTagReader(payload) - if (root.tag.name == "ErrorResponse") { - val errDetails = parseRestXmlErrorResponse(payload) - builder.message = errDetails.message - return InvalidChangeBatchErrorResponse(errDetails, builder.build()) - } - var requestId: String? = null loop@while (true) { val curr = root.nextTag() ?: break@loop - when (curr.tag.name) { + when (curr.tagName) { "Message", "message" -> builder.message = curr.data() "Messages", "messages" -> builder.messages = deserializeMessages(curr) "RequestId" -> requestId = curr.data() @@ -39,7 +32,7 @@ private fun deserializeMessages(root: XmlTagReader): List { val result = mutableListOf() loop@while (true) { val curr = root.nextTag() ?: break@loop - when (curr.tag.name) { + when (curr.tagName) { "Message" -> { val el = curr.tryData().getOrNull() ?: continue@loop result.add(el) diff --git a/services/route53/common/test/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshallingTest.kt b/services/route53/common/test/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshallingTest.kt index de99fd13630..e8a3b2e5b3d 100644 --- a/services/route53/common/test/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshallingTest.kt +++ b/services/route53/common/test/aws/sdk/kotlin/services/route53/internal/ChangeResourceRecordSetsUnmarshallingTest.kt @@ -5,7 +5,6 @@ package aws.sdk.kotlin.services.route53.internal import aws.sdk.kotlin.services.route53.model.InvalidChangeBatch -import aws.sdk.kotlin.services.route53.model.Route53Exception import aws.sdk.kotlin.services.route53.serde.ChangeResourceRecordSetsOperationDeserializer import aws.smithy.kotlin.runtime.http.Headers import aws.smithy.kotlin.runtime.http.HttpBody @@ -107,34 +106,4 @@ class ChangeResourceRecordSetsUnmarshallingTest { assertEquals(listOf("InvalidChangeBatch message 1", "InvalidChangeBatch message 2"), exception.messages) assertEquals("InvalidChangeBatch message 3", exception.message) } - - @Test - fun changeResourceRecordSetsError() { - val bodyText = """ - - - - Sender - MalformedXML - ChangeResourceRecordSets error message - - b25f48e8-84fd-11e6-80d9-574e0c4664cb - - """.trimIndent() - - val response: HttpResponse = HttpResponse( - HttpStatusCode.BadRequest, - Headers.Empty, - HttpBody.fromBytes(bodyText.encodeToByteArray()), - ) - - val call = HttpCall(HttpRequestBuilder().build(), response) - - val exception = assertFailsWith { - runBlocking { - ChangeResourceRecordSetsOperationDeserializer().deserialize(ExecutionContext(), call) - } - } - assertEquals("ChangeResourceRecordSets error message", exception.message) - } } diff --git a/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/Handle200ErrorsInterceptor.kt b/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/Handle200ErrorsInterceptor.kt index aafdf1718e5..c5fe16baeda 100644 --- a/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/Handle200ErrorsInterceptor.kt +++ b/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/Handle200ErrorsInterceptor.kt @@ -32,7 +32,7 @@ internal object Handle200ErrorsInterceptor : HttpInterceptor { // according to the knowledge center article above we should treat these as 5xx, // our retry policy will handle standard error codes like `SlowDown` val statusCode = HttpStatusCode.InternalServerError - .takeIf { token?.qualifiedName?.local == "Error" } + .takeIf { token?.name?.local == "Error" } ?: response.status return response.copy(status = statusCode, body = HttpBody.fromBytes(payload)) } diff --git a/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/S3ErrorMetadata.kt b/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/S3ErrorMetadata.kt index 6f5cb7fef85..45074546fcd 100644 --- a/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/S3ErrorMetadata.kt +++ b/services/s3/common/src/aws/sdk/kotlin/services/s3/internal/S3ErrorMetadata.kt @@ -52,7 +52,7 @@ internal fun parseS3ErrorResponse(payload: ByteArray): S3ErrorDetails { loop@ while (true) { val curr = root.nextTag() ?: break@loop - when (curr.tag.name) { + when (curr.tagName) { "Code" -> code = curr.data() "Message", "message" -> message = curr.data() "RequestId" -> requestId = curr.data() From 0ade972b3eec01a0129b6a28014c29866d0612ff Mon Sep 17 00:00:00 2001 From: Aaron J Todd Date: Tue, 27 Feb 2024 14:44:55 -0500 Subject: [PATCH 09/11] remove fixme --- .../amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt index 27eada3b0ad..c7c834c3175 100644 --- a/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt +++ b/codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/protocols/RestXml.kt @@ -82,7 +82,6 @@ class RestXmlParserGenerator( else -> super.payloadDeserializer(ctx, shape, members) } - // FIXME - reconcile private fun explicitBoundStructureDeserializer( ctx: ProtocolGenerator.GenerationContext, boundMember: MemberShape, From d78f5d479a05f7aab1472a19cc2b97fb32ce34a6 Mon Sep 17 00:00:00 2001 From: Aaron J Todd Date: Tue, 27 Feb 2024 20:49:21 -0500 Subject: [PATCH 10/11] tickle ci From 8dbaea8978bcabb270a3f0a16e68b8018957b504 Mon Sep 17 00:00:00 2001 From: Aaron J Todd Date: Wed, 28 Feb 2024 21:48:23 -0500 Subject: [PATCH 11/11] bump versions --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 88a30d55c61..f19bf376040 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,8 +9,8 @@ coroutines-version = "1.7.3" atomicfu-version = "0.23.1" # smithy-kotlin codegen and runtime are versioned separately -smithy-kotlin-runtime-version = "1.0.16-SNAPSHOT" -smithy-kotlin-codegen-version = "0.30.17-SNAPSHOT" +smithy-kotlin-runtime-version = "1.0.16" +smithy-kotlin-codegen-version = "0.30.17" # codegen smithy-version = "1.42.0"