@@ -77,8 +77,9 @@ public HttpChecksumStage(ClientType clientType) {
7777 public SdkHttpFullRequest .Builder execute (SdkHttpFullRequest .Builder request , RequestExecutionContext context )
7878 throws Exception {
7979
80+ ensurePayloadChecksumStorePresent (context .executionAttributes ());
81+
8082 if (sraSigningEnabled (context )) {
81- ensurePayloadChecksumStorePresent (context .executionAttributes ());
8283 return sraChecksum (request , context );
8384 }
8485
@@ -87,9 +88,10 @@ public SdkHttpFullRequest.Builder execute(SdkHttpFullRequest.Builder request, Re
8788
8889 private SdkHttpFullRequest .Builder legacyChecksum (SdkHttpFullRequest .Builder request , RequestExecutionContext context ) {
8990 ChecksumSpecs resolvedChecksumSpecs = getResolvedChecksumSpecs (context .executionAttributes ());
91+ PayloadChecksumStore checksumStore = getPayloadChecksumStore (context .executionAttributes ());
9092
9193 if (md5ChecksumRequired (request , context )) {
92- addMd5ChecksumInHeader (request );
94+ addMd5ChecksumInHeader (request , checksumStore );
9395 return request ;
9496 }
9597
@@ -99,7 +101,7 @@ private SdkHttpFullRequest.Builder legacyChecksum(SdkHttpFullRequest.Builder req
99101 }
100102
101103 if (flexibleChecksumInHeaderRequired (context , resolvedChecksumSpecs )) {
102- addFlexibleChecksumInHeader (request , context , resolvedChecksumSpecs );
104+ addFlexibleChecksumInHeader (request , context , resolvedChecksumSpecs , checksumStore );
103105 return request ;
104106 }
105107
@@ -174,10 +176,14 @@ private boolean md5ChecksumRequired(SdkHttpFullRequest.Builder request, RequestE
174176 * request body to use that buffered content. We obviously don't want to do that for giant streams, so we haven't opted to do
175177 * that yet.
176178 */
177- private void addMd5ChecksumInHeader (SdkHttpFullRequest .Builder request ) {
179+ private void addMd5ChecksumInHeader (SdkHttpFullRequest .Builder request , PayloadChecksumStore checksumStore ) {
178180 try {
179- String payloadMd5 = Md5Utils .md5AsBase64 (request .contentStreamProvider ().newStream ());
180- request .putHeader (Header .CONTENT_MD5 , payloadMd5 );
181+ byte [] payloadMd5 = checksumStore .getChecksumValue (DefaultChecksumAlgorithm .MD5 );
182+ if (payloadMd5 == null ) {
183+ payloadMd5 = Md5Utils .computeMD5Hash (request .contentStreamProvider ().newStream ());
184+ checksumStore .putChecksumValue (DefaultChecksumAlgorithm .MD5 , payloadMd5 );
185+ }
186+ request .putHeader (Header .CONTENT_MD5 , BinaryUtils .toBase64 (payloadMd5 ));
181187 } catch (IOException e ) {
182188 throw new UncheckedIOException (e );
183189 }
@@ -237,7 +243,11 @@ private void addFlexibleChecksumInTrailer(SdkHttpFullRequest.Builder request, Re
237243 int chunkSize = 0 ;
238244
239245 if (clientType == ClientType .SYNC ) {
240- request .contentStreamProvider (new ChecksumCalculatingStreamProvider (request .contentStreamProvider (), checksumSpecs ));
246+ request .contentStreamProvider (
247+ new ChecksumCalculatingStreamProvider (request .contentStreamProvider (),
248+ checksumSpecs ,
249+ getPayloadChecksumStore (context .executionAttributes ())
250+ ));
241251 originalContentLength =
242252 context .executionContext ().interceptorContext ().requestBody ().get ().optionalContentLength ().orElse (0L );
243253 chunkSize = DEFAULT_CHUNK_SIZE ;
@@ -311,13 +321,19 @@ private boolean flexibleChecksumInHeaderRequired(RequestExecutionContext context
311321 * that yet.
312322 */
313323 private void addFlexibleChecksumInHeader (SdkHttpFullRequest .Builder request , RequestExecutionContext context ,
314- ChecksumSpecs checksumSpecs ) {
324+ ChecksumSpecs checksumSpecs , PayloadChecksumStore checksumStore ) {
315325 try {
316326 Algorithm legacyAlgorithm = checksumSpecs .algorithm ();
317- String payloadChecksum = BinaryUtils .toBase64 (HttpChecksumUtils .computeChecksum (
318- context .executionContext ().interceptorContext ().requestBody ().get ().contentStreamProvider ().newStream (),
319- legacyAlgorithm ));
320- request .putHeader (checksumSpecs .headerName (), payloadChecksum );
327+ ChecksumAlgorithm newAlgorithm = HttpChecksumUtils .toNewChecksumAlgorithm (legacyAlgorithm );
328+ byte [] payloadChecksum = checksumStore .getChecksumValue (newAlgorithm );
329+ if (payloadChecksum == null ) {
330+ payloadChecksum = HttpChecksumUtils .computeChecksum (
331+ context .executionContext ().interceptorContext ().requestBody ().get ().contentStreamProvider ().newStream (),
332+ legacyAlgorithm );
333+ checksumStore .putChecksumValue (newAlgorithm , payloadChecksum );
334+ }
335+ String headerValue = BinaryUtils .toBase64 (payloadChecksum );
336+ request .putHeader (checksumSpecs .headerName (), headerValue );
321337 } catch (IOException e ) {
322338 throw new UncheckedIOException (e );
323339 }
@@ -339,24 +355,31 @@ static final class ChecksumCalculatingStreamProvider implements ContentStreamPro
339355 private final ContentStreamProvider underlyingInputStreamProvider ;
340356 private final String checksumHeaderForTrailer ;
341357 private final ChecksumSpecs checksumSpecs ;
358+ private final PayloadChecksumStore checksumStore ;
342359 private InputStream currentStream ;
360+ private final ChecksumAlgorithm checksumAlgorithm ;
343361 private software .amazon .awssdk .core .checksums .SdkChecksum sdkChecksum ;
344362
345363 ChecksumCalculatingStreamProvider (ContentStreamProvider underlyingInputStreamProvider ,
346- ChecksumSpecs checksumSpecs ) {
364+ ChecksumSpecs checksumSpecs ,
365+ PayloadChecksumStore checksumStore ) {
347366 this .underlyingInputStreamProvider = underlyingInputStreamProvider ;
348367 this .sdkChecksum = software .amazon .awssdk .core .checksums .SdkChecksum .forAlgorithm (
349368 checksumSpecs .algorithm ());
369+ this .checksumAlgorithm = HttpChecksumUtils .toNewChecksumAlgorithm (checksumSpecs .algorithm ());
350370 this .checksumHeaderForTrailer = checksumSpecs .headerName ();
351371 this .checksumSpecs = checksumSpecs ;
372+ this .checksumStore = checksumStore ;
352373 }
353374
354375 @ Override
355376 public InputStream newStream () {
356377 closeCurrentStream ();
357378 currentStream = AwsUnsignedChunkedEncodingInputStream .builder ()
358379 .inputStream (underlyingInputStreamProvider .newStream ())
380+ .checksumAlgorithm (checksumAlgorithm )
359381 .sdkChecksum (sdkChecksum )
382+ .checksumStore (checksumStore )
360383 .checksumHeaderForTrailer (checksumHeaderForTrailer )
361384 .build ();
362385 return currentStream ;
0 commit comments