diff --git a/.changes/42b15168-de5f-46aa-867a-02a28b4a7b31.json b/.changes/42b15168-de5f-46aa-867a-02a28b4a7b31.json new file mode 100644 index 00000000000..2694d0c414f --- /dev/null +++ b/.changes/42b15168-de5f-46aa-867a-02a28b4a7b31.json @@ -0,0 +1,8 @@ +{ + "id": "42b15168-de5f-46aa-867a-02a28b4a7b31", + "type": "bugfix", + "description": "Properly handle members with HTTP header bindings to x-amz-content-sha256", + "issues": [ + "https://github.com/awslabs/aws-sdk-kotlin/issues/1217" + ] +} \ No newline at end of file diff --git a/codegen/aws-sdk-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/customization/UpdateExecutionContextWithXAmzContentSha256HeaderBinding.kt b/codegen/aws-sdk-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/customization/UpdateExecutionContextWithXAmzContentSha256HeaderBinding.kt new file mode 100644 index 00000000000..61ab4fc2acb --- /dev/null +++ b/codegen/aws-sdk-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/customization/UpdateExecutionContextWithXAmzContentSha256HeaderBinding.kt @@ -0,0 +1,47 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package aws.sdk.kotlin.codegen.customization + +import software.amazon.smithy.kotlin.codegen.core.KotlinWriter +import software.amazon.smithy.kotlin.codegen.core.RuntimeTypes +import software.amazon.smithy.kotlin.codegen.core.defaultName +import software.amazon.smithy.kotlin.codegen.core.withBlock +import software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration +import software.amazon.smithy.kotlin.codegen.model.getTrait +import software.amazon.smithy.kotlin.codegen.rendering.protocol.ProtocolGenerator +import software.amazon.smithy.kotlin.codegen.rendering.protocol.ProtocolMiddleware +import software.amazon.smithy.model.shapes.MemberShape +import software.amazon.smithy.model.shapes.OperationShape +import software.amazon.smithy.model.traits.HttpHeaderTrait + +/** + * Registers a middleware which overrides the execution context HashSpecification for members with an HTTP header binding + * to `x-amz-content-sha256`. + * https://github.com/awslabs/aws-sdk-kotlin/issues/1217 + */ +class UpdateExecutionContextWithXAmzContentSha256HeaderBinding : KotlinIntegration { + override fun customizeMiddleware( + ctx: ProtocolGenerator.GenerationContext, + resolved: List, + ): List = resolved + UpdateExecutionContextWithSha256HeaderBindingMiddleware() +} + +private class UpdateExecutionContextWithSha256HeaderBindingMiddleware : ProtocolMiddleware { + override val name: String = "UpdateExecutionContextWithXAmzContentSha256HeaderBinding" + + override fun isEnabledFor(ctx: ProtocolGenerator.GenerationContext, op: OperationShape): Boolean = getXAmzContentSha256HeaderMember(ctx, op) != null + + override fun render(ctx: ProtocolGenerator.GenerationContext, op: OperationShape, writer: KotlinWriter) { + val member = getXAmzContentSha256HeaderMember(ctx, op)!! + writer.withBlock("input.${member.defaultName()}?.let {", "}") { + writer.write("op.context[#1T.#2T] = #2T.Precalculated(it)", RuntimeTypes.Auth.Signing.AwsSigningCommon.AwsSigningAttributes, RuntimeTypes.Auth.Signing.AwsSigningCommon.HashSpecification) + } + } + + private fun getXAmzContentSha256HeaderMember(ctx: ProtocolGenerator.GenerationContext, op: OperationShape): MemberShape? { + val input = ctx.model.expectShape(op.inputShape) + return input.members().singleOrNull { it.getTrait()?.value?.equals("x-amz-content-sha256") ?: false } + } +} diff --git a/codegen/aws-sdk-codegen/src/main/resources/META-INF/services/software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration b/codegen/aws-sdk-codegen/src/main/resources/META-INF/services/software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration index 1eeb8f5a1d3..74035829c00 100644 --- a/codegen/aws-sdk-codegen/src/main/resources/META-INF/services/software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration +++ b/codegen/aws-sdk-codegen/src/main/resources/META-INF/services/software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration @@ -39,3 +39,4 @@ aws.sdk.kotlin.codegen.customization.RemoveDefaults aws.sdk.kotlin.codegen.customization.s3.UnsupportedSigningAlgorithmIntegration aws.sdk.kotlin.codegen.customization.SigV4AsymmetricTraitCustomization aws.sdk.kotlin.codegen.customization.cloudfrontkeyvaluestore.BackfillSigV4ACustomization +aws.sdk.kotlin.codegen.customization.UpdateExecutionContextWithXAmzContentSha256HeaderBinding \ No newline at end of file