diff --git a/Sources/ClientRuntime/Networking/Http/Middlewares/ContentMD5Middleware.swift b/Sources/ClientRuntime/Networking/Http/Middlewares/ContentMD5Middleware.swift index e8dacb238..b272a90a4 100644 --- a/Sources/ClientRuntime/Networking/Http/Middlewares/ContentMD5Middleware.swift +++ b/Sources/ClientRuntime/Networking/Http/Middlewares/ContentMD5Middleware.swift @@ -15,8 +15,24 @@ public struct ContentMD5Middleware { public init() {} private func addHeaders(builder: HTTPRequestBuilder, attributes: Context) async throws { - // Skip MD5 hash if using checksums - if builder.headers.exists(name: "x-amz-sdk-checksum-algorithm") { + // Initialize logger + guard let logger = attributes.getLogger() else { + throw ClientError.unknownError("No logger found!") + } + + // Skip MD5 hash if using flexible checksum + if builder.headers.headers.contains(where: { + $0.name.lowercased().starts(with: "x-amz-checksum-") + }) { + logger.debug("Flexible checksum configured. Skipping MD5 checksum calculation.") + return + } + + // Skip MD5 hash if it was provided in input by the user + if builder.headers.headers.contains(where: { + $0.name.lowercased() == "content-md5" + }) { + logger.debug("MD5 checksum hash provided in the input. Skipping MD5 checksum calculation.") return } @@ -42,15 +58,9 @@ public struct ContentMD5Middleware { let hashResult = try md5Hasher.digest().toBase64String() builder.updateHeader(name: "Content-MD5", value: hashResult) } catch { - guard let logger = attributes.getLogger() else { - return - } logger.error("Could not compute Content-MD5 of stream due to error \(error)") } default: - guard let logger = attributes.getLogger() else { - return - } logger.error("Unhandled case for Content-MD5") } } diff --git a/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/integration/middlewares/ContentMD5Middleware.kt b/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/integration/middlewares/ContentMD5Middleware.kt index c36764d7f..ee415dc66 100644 --- a/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/integration/middlewares/ContentMD5Middleware.kt +++ b/smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/integration/middlewares/ContentMD5Middleware.kt @@ -38,8 +38,18 @@ class ContentMD5Middleware( /** * Check if MD5 checksum is required - * The Md5 middleware will only be installed if the operation requires a checksum and the user has not opted-in to flexible checksums. + * The Md5 middleware will only be generated if the operation is marked with @httpChecksumRequired trait or if + * only the requestChecksumRequired property of the httpChecksum is set. + * https://smithy.io/2.0/aws/aws-core.html#behavior-with-httpchecksumrequired + * + * ContentMD5Middleware will skip checksum calculation if flexible checksum was calculated for request already, + * determined by presence of a header with "x-amz-checksum-" prefix. */ -private fun OperationShape.isMD5ChecksumRequired(): Boolean = - // the checksum requirement can be modeled in either HttpChecksumTrait's `requestChecksumRequired` or the HttpChecksumRequired trait - getTrait()?.isRequestChecksumRequired == true || hasTrait() +private fun OperationShape.isMD5ChecksumRequired(): Boolean { + val httpChecksumTrait = getTrait() + val onlyRequestChecksumRequiredIsSetInHttpChecksumTrait = httpChecksumTrait?.isRequestChecksumRequired == true && + httpChecksumTrait.requestAlgorithmMember?.isEmpty == true && + httpChecksumTrait.requestValidationModeMember?.isEmpty == true && + httpChecksumTrait.responseAlgorithms?.isEmpty() == true + return onlyRequestChecksumRequiredIsSetInHttpChecksumTrait || hasTrait() +}