From 292a8ae2cae16dd88a79068aad2a7382ce929bc0 Mon Sep 17 00:00:00 2001 From: kzhsw <120431159+kzhsw@users.noreply.github.com> Date: Thu, 2 Jan 2025 15:16:32 +0800 Subject: [PATCH 1/5] ObjectWriteResponse: return checksums if any Currently `PutObject`, `CopyObject`, `CompleteMultipartUpload` could return checksums, but client api for `CopyObjectResult` and `ObjectWriteResponse` does not return it. This commit adds checksums to `CopyObjectResult` and `ObjectWriteResponse` to allow users to get checksums if any. Close https://github.com/minio/minio-java/issues/1608 References: --- .../main/java/io/minio/MinioAsyncClient.java | 6 +++- .../java/io/minio/ObjectWriteResponse.java | 33 +++++++++++++++++++ api/src/main/java/io/minio/S3Base.java | 18 ++++++++-- .../io/minio/messages/CopyObjectResult.java | 28 ++++++++++++++++ 4 files changed, 81 insertions(+), 4 deletions(-) diff --git a/api/src/main/java/io/minio/MinioAsyncClient.java b/api/src/main/java/io/minio/MinioAsyncClient.java index c9c105f81..f5df4b9f5 100644 --- a/api/src/main/java/io/minio/MinioAsyncClient.java +++ b/api/src/main/java/io/minio/MinioAsyncClient.java @@ -532,7 +532,11 @@ public CompletableFuture copyObject(CopyObjectArgs args) args.region(), args.object(), result.etag(), - response.header("x-amz-version-id")); + response.header("x-amz-version-id"), + result.checksumCRC32(), + result.checksumCRC32C(), + result.checksumSHA1(), + result.checksumSHA256()); } catch (XmlParserException e) { throw new CompletionException(e); } finally { diff --git a/api/src/main/java/io/minio/ObjectWriteResponse.java b/api/src/main/java/io/minio/ObjectWriteResponse.java index 1083a1252..1d4aec6ba 100644 --- a/api/src/main/java/io/minio/ObjectWriteResponse.java +++ b/api/src/main/java/io/minio/ObjectWriteResponse.java @@ -22,6 +22,10 @@ public class ObjectWriteResponse extends GenericResponse { private String etag; private String versionId; + private String checksumCRC32; + private String checksumCRC32C; + private String checksumSHA1; + private String checksumSHA256; public ObjectWriteResponse( Headers headers, String bucket, String region, String object, String etag, String versionId) { @@ -30,6 +34,19 @@ public ObjectWriteResponse( this.versionId = versionId; } + public ObjectWriteResponse( + Headers headers, String bucket, String region, String object, String etag, String versionId, + String checksumCRC32, String checksumCRC32C, String checksumSHA1, String checksumSHA256 + ) { + super(headers, bucket, region, object); + this.etag = etag; + this.versionId = versionId; + this.checksumCRC32 = checksumCRC32; + this.checksumCRC32C = checksumCRC32C; + this.checksumSHA1 = checksumSHA1; + this.checksumSHA256 = checksumSHA256; + } + public String etag() { return etag; } @@ -37,4 +54,20 @@ public String etag() { public String versionId() { return versionId; } + + public String checksumCRC32() { + return checksumCRC32; + } + + public String checksumCRC32C() { + return checksumCRC32C; + } + + public String checksumSHA1() { + return checksumSHA1; + } + + public String checksumSHA256() { + return checksumSHA256; + } } diff --git a/api/src/main/java/io/minio/S3Base.java b/api/src/main/java/io/minio/S3Base.java index c9adc8a71..bb0fd6cb3 100644 --- a/api/src/main/java/io/minio/S3Base.java +++ b/api/src/main/java/io/minio/S3Base.java @@ -2015,7 +2015,11 @@ public CompletableFuture completeMultipartUploadAsync( result.location(), result.object(), result.etag(), - response.header("x-amz-version-id")); + response.header("x-amz-version-id"), + result.checksumCRC32(), + result.checksumCRC32C(), + result.checksumSHA1(), + result.checksumSHA256()); } catch (XmlParserException e) { // As this CompleteMultipartUpload REST call succeeded, just log it. Logger.getLogger(S3Base.class.getName()) @@ -3012,7 +3016,11 @@ private CompletableFuture putObjectAsync( region, objectName, response.header("ETag").replaceAll("\"", ""), - response.header("x-amz-version-id")); + response.header("x-amz-version-id"), + response.header("x-amz-checksum-crc32"), + response.header("x-amz-checksum-crc32c"), + response.header("x-amz-checksum-sha1"), + response.header("x-amz-checksum-sha256")); } finally { response.close(); } @@ -3093,7 +3101,11 @@ protected CompletableFuture putObjectAsync( region, objectName, response.header("ETag").replaceAll("\"", ""), - response.header("x-amz-version-id")); + response.header("x-amz-version-id"), + response.header("x-amz-checksum-crc32"), + response.header("x-amz-checksum-crc32c"), + response.header("x-amz-checksum-sha1"), + response.header("x-amz-checksum-sha256")); } finally { response.close(); } diff --git a/api/src/main/java/io/minio/messages/CopyObjectResult.java b/api/src/main/java/io/minio/messages/CopyObjectResult.java index 53b0b795e..107f99ebf 100644 --- a/api/src/main/java/io/minio/messages/CopyObjectResult.java +++ b/api/src/main/java/io/minio/messages/CopyObjectResult.java @@ -35,6 +35,18 @@ public class CopyObjectResult { @Element(name = "LastModified") private ResponseDate lastModified; + @Element(name = "ChecksumCRC32", required = false) + private String checksumCRC32; + + @Element(name = "ChecksumCRC32C", required = false) + private String checksumCRC32C; + + @Element(name = "ChecksumSHA1", required = false) + private String checksumSHA1; + + @Element(name = "ChecksumSHA256", required = false) + private String checksumSHA256; + public CopyObjectResult() {} /** Returns ETag of the object. */ @@ -46,4 +58,20 @@ public String etag() { public ZonedDateTime lastModified() { return lastModified.zonedDateTime(); } + + public String checksumCRC32() { + return checksumCRC32; + } + + public String checksumCRC32C() { + return checksumCRC32C; + } + + public String checksumSHA1() { + return checksumSHA1; + } + + public String checksumSHA256() { + return checksumSHA256; + } } From 6ca8e60a45871d76920f311beeb0357a1237e6cf Mon Sep 17 00:00:00 2001 From: kzhsw <120431159+kzhsw@users.noreply.github.com> Date: Mon, 6 Jan 2025 08:51:21 +0800 Subject: [PATCH 2/5] ObjectWriteResponse: update constructor 1. By default, populate checksums from headers 2. Accept CopyObjectResult as an additional argument and populate checksums 2. Accept CompleteMultipartUploadResult as an additional argument and populate checksums --- .../main/java/io/minio/MinioAsyncClient.java | 5 +-- .../java/io/minio/ObjectWriteResponse.java | 35 ++++++++++++++++--- api/src/main/java/io/minio/S3Base.java | 17 ++------- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/api/src/main/java/io/minio/MinioAsyncClient.java b/api/src/main/java/io/minio/MinioAsyncClient.java index f5df4b9f5..715559b09 100644 --- a/api/src/main/java/io/minio/MinioAsyncClient.java +++ b/api/src/main/java/io/minio/MinioAsyncClient.java @@ -533,10 +533,7 @@ public CompletableFuture copyObject(CopyObjectArgs args) args.object(), result.etag(), response.header("x-amz-version-id"), - result.checksumCRC32(), - result.checksumCRC32C(), - result.checksumSHA1(), - result.checksumSHA256()); + result); } catch (XmlParserException e) { throw new CompletionException(e); } finally { diff --git a/api/src/main/java/io/minio/ObjectWriteResponse.java b/api/src/main/java/io/minio/ObjectWriteResponse.java index 1d4aec6ba..6a92be56c 100644 --- a/api/src/main/java/io/minio/ObjectWriteResponse.java +++ b/api/src/main/java/io/minio/ObjectWriteResponse.java @@ -17,6 +17,8 @@ package io.minio; import okhttp3.Headers; +import io.minio.messages.CopyObjectResult; +import io.minio.messages.CompleteMultipartUploadOutput; /** Response class of any APIs doing object creation. */ public class ObjectWriteResponse extends GenericResponse { @@ -32,19 +34,42 @@ public ObjectWriteResponse( super(headers, bucket, region, object); this.etag = etag; this.versionId = versionId; + if (headers != null) { + this.checksumCRC32 = headers.get("x-amz-checksum-crc32"); + this.checksumCRC32C = headers.get("x-amz-checksum-crc32c"); + this.checksumSHA1 = headers.get("x-amz-checksum-sha1"); + this.checksumSHA256 = headers.get("x-amz-checksum-sha256"); + } } public ObjectWriteResponse( Headers headers, String bucket, String region, String object, String etag, String versionId, - String checksumCRC32, String checksumCRC32C, String checksumSHA1, String checksumSHA256 + CopyObjectResult result + ) { + super(headers, bucket, region, object); + this.etag = etag; + this.versionId = versionId; + if (result != null) { + this.checksumCRC32 = result.checksumCRC32(), + this.checksumCRC32C = result.checksumCRC32C(), + this.checksumSHA1 = result.checksumSHA1(), + this.checksumSHA256 = result.checksumSHA256() + } + } + + public ObjectWriteResponse( + Headers headers, String bucket, String region, String object, String etag, String versionId, + CompleteMultipartUploadResult result ) { super(headers, bucket, region, object); this.etag = etag; this.versionId = versionId; - this.checksumCRC32 = checksumCRC32; - this.checksumCRC32C = checksumCRC32C; - this.checksumSHA1 = checksumSHA1; - this.checksumSHA256 = checksumSHA256; + if (result != null) { + this.checksumCRC32 = result.checksumCRC32(), + this.checksumCRC32C = result.checksumCRC32C(), + this.checksumSHA1 = result.checksumSHA1(), + this.checksumSHA256 = result.checksumSHA256() + } } public String etag() { diff --git a/api/src/main/java/io/minio/S3Base.java b/api/src/main/java/io/minio/S3Base.java index bb0fd6cb3..91dba0e7f 100644 --- a/api/src/main/java/io/minio/S3Base.java +++ b/api/src/main/java/io/minio/S3Base.java @@ -2016,10 +2016,7 @@ public CompletableFuture completeMultipartUploadAsync( result.object(), result.etag(), response.header("x-amz-version-id"), - result.checksumCRC32(), - result.checksumCRC32C(), - result.checksumSHA1(), - result.checksumSHA256()); + result); } catch (XmlParserException e) { // As this CompleteMultipartUpload REST call succeeded, just log it. Logger.getLogger(S3Base.class.getName()) @@ -3016,11 +3013,7 @@ private CompletableFuture putObjectAsync( region, objectName, response.header("ETag").replaceAll("\"", ""), - response.header("x-amz-version-id"), - response.header("x-amz-checksum-crc32"), - response.header("x-amz-checksum-crc32c"), - response.header("x-amz-checksum-sha1"), - response.header("x-amz-checksum-sha256")); + response.header("x-amz-version-id")); } finally { response.close(); } @@ -3101,11 +3094,7 @@ protected CompletableFuture putObjectAsync( region, objectName, response.header("ETag").replaceAll("\"", ""), - response.header("x-amz-version-id"), - response.header("x-amz-checksum-crc32"), - response.header("x-amz-checksum-crc32c"), - response.header("x-amz-checksum-sha1"), - response.header("x-amz-checksum-sha256")); + response.header("x-amz-version-id")); } finally { response.close(); } From b9e60d30425222b10edf1bdc13285cfdd662fb50 Mon Sep 17 00:00:00 2001 From: kzhsw <120431159+kzhsw@users.noreply.github.com> Date: Mon, 6 Jan 2025 11:51:57 +0800 Subject: [PATCH 3/5] ObjectWriteResponse: fix typo --- .../main/java/io/minio/ObjectWriteResponse.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/api/src/main/java/io/minio/ObjectWriteResponse.java b/api/src/main/java/io/minio/ObjectWriteResponse.java index 6a92be56c..ed1aec778 100644 --- a/api/src/main/java/io/minio/ObjectWriteResponse.java +++ b/api/src/main/java/io/minio/ObjectWriteResponse.java @@ -50,10 +50,10 @@ public ObjectWriteResponse( this.etag = etag; this.versionId = versionId; if (result != null) { - this.checksumCRC32 = result.checksumCRC32(), - this.checksumCRC32C = result.checksumCRC32C(), - this.checksumSHA1 = result.checksumSHA1(), - this.checksumSHA256 = result.checksumSHA256() + this.checksumCRC32 = result.checksumCRC32(); + this.checksumCRC32C = result.checksumCRC32C(); + this.checksumSHA1 = result.checksumSHA1(); + this.checksumSHA256 = result.checksumSHA256(); } } @@ -65,10 +65,10 @@ public ObjectWriteResponse( this.etag = etag; this.versionId = versionId; if (result != null) { - this.checksumCRC32 = result.checksumCRC32(), - this.checksumCRC32C = result.checksumCRC32C(), - this.checksumSHA1 = result.checksumSHA1(), - this.checksumSHA256 = result.checksumSHA256() + this.checksumCRC32 = result.checksumCRC32(); + this.checksumCRC32C = result.checksumCRC32C(); + this.checksumSHA1 = result.checksumSHA1(); + this.checksumSHA256 = result.checksumSHA256(); } } From 5c83aace48cfe8e6197065e2043afb67e00acb4f Mon Sep 17 00:00:00 2001 From: kzhsw <120431159+kzhsw@users.noreply.github.com> Date: Mon, 6 Jan 2025 14:42:14 +0800 Subject: [PATCH 4/5] ObjectWriteResponse: fix build --- api/src/main/java/io/minio/ObjectWriteResponse.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/io/minio/ObjectWriteResponse.java b/api/src/main/java/io/minio/ObjectWriteResponse.java index ed1aec778..93e6c91c7 100644 --- a/api/src/main/java/io/minio/ObjectWriteResponse.java +++ b/api/src/main/java/io/minio/ObjectWriteResponse.java @@ -59,7 +59,7 @@ public ObjectWriteResponse( public ObjectWriteResponse( Headers headers, String bucket, String region, String object, String etag, String versionId, - CompleteMultipartUploadResult result + CompleteMultipartUploadOutput result ) { super(headers, bucket, region, object); this.etag = etag; From d5be923e8237a3afc7fcc51d1fac373f57f9cd33 Mon Sep 17 00:00:00 2001 From: kzhsw <120431159+kzhsw@users.noreply.github.com> Date: Mon, 6 Jan 2025 15:45:12 +0800 Subject: [PATCH 5/5] ObjectWriteResponse: fix spotlessApply --- .../java/io/minio/ObjectWriteResponse.java | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/api/src/main/java/io/minio/ObjectWriteResponse.java b/api/src/main/java/io/minio/ObjectWriteResponse.java index 93e6c91c7..b9ba17834 100644 --- a/api/src/main/java/io/minio/ObjectWriteResponse.java +++ b/api/src/main/java/io/minio/ObjectWriteResponse.java @@ -16,9 +16,9 @@ package io.minio; -import okhttp3.Headers; -import io.minio.messages.CopyObjectResult; import io.minio.messages.CompleteMultipartUploadOutput; +import io.minio.messages.CopyObjectResult; +import okhttp3.Headers; /** Response class of any APIs doing object creation. */ public class ObjectWriteResponse extends GenericResponse { @@ -43,9 +43,13 @@ public ObjectWriteResponse( } public ObjectWriteResponse( - Headers headers, String bucket, String region, String object, String etag, String versionId, - CopyObjectResult result - ) { + Headers headers, + String bucket, + String region, + String object, + String etag, + String versionId, + CopyObjectResult result) { super(headers, bucket, region, object); this.etag = etag; this.versionId = versionId; @@ -58,9 +62,13 @@ public ObjectWriteResponse( } public ObjectWriteResponse( - Headers headers, String bucket, String region, String object, String etag, String versionId, - CompleteMultipartUploadOutput result - ) { + Headers headers, + String bucket, + String region, + String object, + String etag, + String versionId, + CompleteMultipartUploadOutput result) { super(headers, bucket, region, object); this.etag = etag; this.versionId = versionId;