Skip to content

Commit fa52523

Browse files
authored
fix: usage of pre-calculated checksum values (#852)
1 parent aa491d9 commit fa52523

File tree

5 files changed

+36
-4
lines changed

5 files changed

+36
-4
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"id": "47b592af-ba43-43ad-b38b-534845549cfd",
3+
"type": "bugfix",
4+
"description": "Fix usage of precalculated checksum values"
5+
}

runtime/protocol/http-client/api/http-client.api

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ public final class aws/smithy/kotlin/runtime/http/engine/TlsContext$Companion {
136136
public final class aws/smithy/kotlin/runtime/http/engine/internal/ManagedHttpClientEngineKt {
137137
}
138138

139+
public final class aws/smithy/kotlin/runtime/http/interceptors/ChecksumMismatchException : aws/smithy/kotlin/runtime/ClientException {
140+
public fun <init> (Ljava/lang/String;)V
141+
}
142+
139143
public final class aws/smithy/kotlin/runtime/http/interceptors/FlexibleChecksumsResponseInterceptor$Companion {
140144
public final fun getChecksumHeaderValidated ()Laws/smithy/kotlin/runtime/util/AttributeKey;
141145
}

runtime/protocol/http-client/common/src/aws/smithy/kotlin/runtime/http/interceptors/FlexibleChecksumsRequestInterceptor.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ public class FlexibleChecksumsRequestInterceptor<I>(
4242
checksumAlgorithmName = checksumAlgorithmNameInitializer(input)
4343
}
4444

45-
@OptIn(ExperimentalCoroutinesApi::class)
4645
override suspend fun modifyBeforeRetryLoop(context: ProtocolRequestInterceptorContext<Any, HttpRequest>): HttpRequest {
4746
val logger = coroutineContext.getLogger<FlexibleChecksumsRequestInterceptor<I>>()
4847

@@ -57,7 +56,7 @@ public class FlexibleChecksumsRequestInterceptor<I>(
5756
"Can't calculate the checksum of an empty body"
5857
}
5958

60-
val headerName = "x-amz-checksum-$checksumAlgorithmName"
59+
val headerName = "x-amz-checksum-$checksumAlgorithmName".lowercase()
6160
logger.debug { "Resolved checksum header name: $headerName" }
6261

6362
// remove all checksum headers except for $headerName
@@ -140,7 +139,7 @@ public class FlexibleChecksumsRequestInterceptor<I>(
140139
* Convert an [HttpBody] with an underlying [HashingSource] or [HashingByteReadChannel]
141140
* to a [CompletingSource] or [CompletingByteReadChannel], respectively.
142141
*/
143-
internal fun HttpBody.toCompletingBody(deferred: CompletableDeferred<String>) = when (this) {
142+
private fun HttpBody.toCompletingBody(deferred: CompletableDeferred<String>) = when (this) {
144143
is HttpBody.SourceContent -> CompletingSource(deferred, (readFrom() as HashingSource)).toHttpBody(contentLength)
145144
is HttpBody.ChannelContent -> CompletingByteReadChannel(deferred, (readFrom() as HashingByteReadChannel)).toHttpBody(contentLength)
146145
else -> throw ClientException("HttpBody type is not supported")

runtime/protocol/http-client/common/src/aws/smithy/kotlin/runtime/http/interceptors/FlexibleChecksumsResponseInterceptor.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public class FlexibleChecksumsResponseInterceptor<I>(
8383
}
8484
}
8585

86-
internal class ChecksumMismatchException(message: String?) : ClientException(message)
86+
public class ChecksumMismatchException(message: String?) : ClientException(message)
8787

8888
/**
8989
* An [SdkSource] which validates the underlying [hashingSource]'s checksum against an [expectedChecksum].

runtime/protocol/http-client/common/test/aws/smithy/kotlin/runtime/http/interceptors/FlexibleChecksumsRequestInterceptorTest.kt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,30 @@ class FlexibleChecksumsRequestInterceptorTest {
181181
assertEquals(expectedHash.digest().encodeBase64String(), completableDeferred.getCompleted())
182182
}
183183

184+
@Test
185+
fun itUsesPrecalculatedChecksum() = runTest {
186+
val req = HttpRequestBuilder().apply {
187+
body = ByteArrayContent("<Foo>bar</Foo>".encodeToByteArray())
188+
}
189+
val checksumAlgorithmName = "sha256"
190+
val precalculatedChecksumValue = "sha256-checksum-value"
191+
req.headers { append("x-amz-checksum-$checksumAlgorithmName", precalculatedChecksumValue) }
192+
193+
val op = newTestOperation<Unit, Unit>(req, Unit)
194+
195+
op.interceptors.add(
196+
FlexibleChecksumsRequestInterceptor<Unit> {
197+
checksumAlgorithmName
198+
},
199+
)
200+
201+
op.roundTrip(client, Unit)
202+
val call = op.context.attributes[HttpOperationContext.HttpCallList].first()
203+
204+
assertEquals(1, call.request.headers.getNumChecksumHeaders())
205+
assertEquals(precalculatedChecksumValue, call.request.headers["x-amz-checksum-sha256"])
206+
}
207+
184208
private fun Headers.getNumChecksumHeaders(): Long = entries().stream()
185209
.filter { (name, _) -> name.startsWith("x-amz-checksum-") }
186210
.count()

0 commit comments

Comments
 (0)