Skip to content

Commit ba2f4cc

Browse files
committed
fix: support PutObjectResponse fields
1 parent 599f941 commit ba2f4cc

File tree

5 files changed

+170
-51
lines changed

5 files changed

+170
-51
lines changed

src/main/java/software/amazon/encryption/s3/S3EncryptionClient.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import software.amazon.awssdk.services.s3.model.UploadPartRequest;
4747
import software.amazon.awssdk.services.s3.model.UploadPartResponse;
4848
import software.amazon.encryption.s3.algorithms.AlgorithmSuite;
49+
import software.amazon.encryption.s3.internal.ConvertSDKRequests;
4950
import software.amazon.encryption.s3.internal.GetEncryptedObjectPipeline;
5051
import software.amazon.encryption.s3.internal.InstructionFileConfig;
5152
import software.amazon.encryption.s3.internal.MultiFileOutputStream;
@@ -192,11 +193,7 @@ public PutObjectResponse putObject(PutObjectRequest putObjectRequest, RequestBod
192193

193194
if (_enableMultipartPutObject) {
194195
try {
195-
CompleteMultipartUploadResponse completeResponse = multipartPutObject(putObjectRequest, requestBody);
196-
PutObjectResponse response = PutObjectResponse.builder()
197-
.eTag(completeResponse.eTag())
198-
.build();
199-
return response;
196+
return multipartPutObject(putObjectRequest, requestBody);
200197
} catch (Throwable e) {
201198
throw new S3EncryptionClientException("Exception while performing Multipart Upload PutObject", e);
202199
}
@@ -274,7 +271,7 @@ public <T> T getObject(GetObjectRequest getObjectRequest,
274271
}
275272
}
276273

277-
private CompleteMultipartUploadResponse multipartPutObject(PutObjectRequest request, RequestBody requestBody) throws Throwable {
274+
private PutObjectResponse multipartPutObject(PutObjectRequest request, RequestBody requestBody) throws Throwable {
278275
// Similar logic exists in the MultipartUploadObjectPipeline,
279276
// but the request types do not match so refactoring is not possible
280277
final long contentLength;
@@ -354,7 +351,7 @@ private CompleteMultipartUploadResponse multipartPutObject(PutObjectRequest requ
354351
outputStream.cleanup();
355352
}
356353
// Complete upload
357-
return observer.onCompletion(partETags);
354+
return ConvertSDKRequests.convertResponse(observer.onCompletion(partETags));
358355
}
359356

360357
private <T extends Throwable> T onAbort(UploadObjectObserver observer, T t) {

src/main/java/software/amazon/encryption/s3/internal/ConvertSDKRequests.java

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
package software.amazon.encryption.s3.internal;
22

3+
import java.time.Instant;
4+
import java.util.Map;
5+
36
import software.amazon.awssdk.services.s3.model.ChecksumType;
7+
import software.amazon.awssdk.services.s3.model.CompleteMultipartUploadResponse;
48
import software.amazon.awssdk.services.s3.model.CreateMultipartUploadRequest;
59
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
6-
import java.time.Instant;
7-
import java.util.Map;
10+
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
811

912
public class ConvertSDKRequests {
1013

11-
public static CreateMultipartUploadRequest convert(PutObjectRequest request) {
14+
public static CreateMultipartUploadRequest convertRequest(PutObjectRequest request) {
1215

1316
final CreateMultipartUploadRequest.Builder output = CreateMultipartUploadRequest.builder();
1417
request
@@ -140,6 +143,70 @@ public static CreateMultipartUploadRequest convert(PutObjectRequest request) {
140143
.build();
141144
}
142145

146+
public static PutObjectResponse convertResponse(CompleteMultipartUploadResponse response) {
147+
final PutObjectResponse.Builder output = PutObjectResponse.builder();
148+
response
149+
.toBuilder()
150+
.sdkFields()
151+
.forEach(f -> {
152+
final Object value = f.getValueOrDefault(response);
153+
if (value != null) {
154+
switch (f.memberName()) {
155+
case "ETag":
156+
output.eTag((String) value);
157+
break;
158+
case "Expiration":
159+
output.expiration((String) value);
160+
break;
161+
case "ChecksumCRC32":
162+
output.checksumCRC32((String) value);
163+
break;
164+
case "ChecksumCRC32C":
165+
output.checksumCRC32C((String) value);
166+
break;
167+
case "ChecksumCRC64NVME":
168+
output.checksumCRC64NVME((String) value);
169+
break;
170+
case "ChecksumSHA1":
171+
output.checksumSHA1((String) value);
172+
break;
173+
case "ChecksumSHA256":
174+
output.checksumSHA256((String) value);
175+
break;
176+
case "ChecksumType":
177+
output.checksumType((String) value);
178+
break;
179+
case "ServerSideEncryption":
180+
output.serverSideEncryption((String) value);
181+
break;
182+
case "VersionId":
183+
output.versionId((String) value);
184+
break;
185+
case "SSEKMSKeyId":
186+
output.ssekmsKeyId((String) value);
187+
break;
188+
case "BucketKeyEnabled":
189+
output.bucketKeyEnabled((Boolean) value);
190+
break;
191+
case "RequestCharged":
192+
output.requestCharged((String) value);
193+
break;
194+
// Ignored fields: Location, Bucket, Key
195+
case "Location":
196+
case "Bucket":
197+
case "Key":
198+
// These fields exist only in CompleteMultipartUploadResponse, not in PutObjectResponse
199+
break;
200+
default:
201+
// We should silently drop unknown fields because,
202+
// once the object is stored we expect to return success response.
203+
break;
204+
}
205+
}
206+
});
207+
return output.build();
208+
}
209+
143210
private static boolean isStringStringMap(Object value) {
144211
if (!(value instanceof Map)) {
145212
return false;

src/main/java/software/amazon/encryption/s3/internal/UploadObjectObserver.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public UploadObjectObserver init(PutObjectRequest req,
4444

4545
public String onUploadCreation(PutObjectRequest req) {
4646
CreateMultipartUploadResponse res =
47-
s3EncryptionClient.createMultipartUpload(ConvertSDKRequests.convert(req));
47+
s3EncryptionClient.createMultipartUpload(ConvertSDKRequests.convertRequest(req));
4848
return this.uploadId = res.uploadId();
4949
}
5050

src/test/java/software/amazon/encryption/s3/S3EncryptionClientMultipartUploadTest.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,16 @@
1313
import software.amazon.awssdk.core.sync.RequestBody;
1414
import software.amazon.awssdk.services.s3.S3AsyncClient;
1515
import software.amazon.awssdk.services.s3.S3Client;
16+
import software.amazon.awssdk.services.s3.model.ChecksumType;
1617
import software.amazon.awssdk.services.s3.model.CompletedPart;
1718
import software.amazon.awssdk.services.s3.model.CreateMultipartUploadResponse;
1819
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
1920
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
2021
import software.amazon.awssdk.services.s3.model.SdkPartType;
22+
import software.amazon.awssdk.services.s3.model.ServerSideEncryption;
23+
import software.amazon.awssdk.services.s3.model.StorageClass;
2124
import software.amazon.awssdk.services.s3.model.UploadPartRequest;
2225
import software.amazon.awssdk.services.s3.model.UploadPartResponse;
23-
import software.amazon.awssdk.services.s3.model.StorageClass;
2426
import software.amazon.awssdk.utils.IoUtils;
2527
import software.amazon.encryption.s3.utils.BoundedInputStream;
2628

@@ -543,18 +545,23 @@ public void multipartPutObjectWithOptions() throws IOException {
543545

544546
final StorageClass storageClass = StorageClass.INTELLIGENT_TIERING;
545547

546-
v3Client.putObject(builder -> builder
548+
// PutObject
549+
final PutObjectResponse putObjectResponse = v3Client.putObject(builder -> builder
547550
.bucket(BUCKET)
548551
.overrideConfiguration(withAdditionalConfiguration(encryptionContext))
549552
.storageClass(storageClass)
550553
.key(objectKey), RequestBody.fromInputStream(inputStream, fileSizeLimit));
551554

552-
// Asserts
555+
assertEquals(ChecksumType.FULL_OBJECT.toString(), putObjectResponse.checksumTypeAsString());
556+
assertEquals(ServerSideEncryption.AES256.toString(), putObjectResponse.serverSideEncryptionAsString());
557+
558+
// GetObject
553559
final ResponseInputStream<GetObjectResponse> output = v3Client.getObject(builder -> builder
554560
.bucket(BUCKET)
555561
.overrideConfiguration(S3EncryptionClient.withAdditionalConfiguration(encryptionContext))
556562
.key(objectKey));
557563

564+
// Asserts
558565
assertTrue(IOUtils.contentEquals(objectStreamForResult, output));
559566
assertEquals(storageClass, output.response().storageClass());
560567

0 commit comments

Comments
 (0)