From 6195b80349ca5f406bd70c6b4aea9dd8dd40192a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Friedrich=20Dreyer?= Date: Fri, 4 Aug 2023 11:37:35 +0200 Subject: [PATCH] Support sending precalculated Content-MD5 header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We already have the MD5 of the content and want to send along the Content-MD5 header without minio-go having to recalculate the hash. With this PR we can set `SendContentMd5: false` and send our hash as `UserMetadata`. Signed-off-by: Jörn Friedrich Dreyer --- functional_tests.go | 64 +++++++++++++++++++++++++++++++++++++++++++++ utils.go | 1 + 2 files changed, 65 insertions(+) diff --git a/functional_tests.go b/functional_tests.go index f951cd073..ac734ac36 100644 --- a/functional_tests.go +++ b/functional_tests.go @@ -11391,6 +11391,70 @@ func testPutObject0ByteV2() { successLogger(testName, function, args, startTime).Info() } +// Test put object with precalculated content md5. +func testPutObjectContentMD5() { + // initialize logging params + startTime := time.Now() + testName := getFuncName() + function := "PutObject(bucketName, objectName, reader, size, opts)" + args := map[string]interface{}{ + "bucketName": "", + "objectName": "", + "size": 3, + "opts": minio.PutObjectOptions{ + SendContentMd5: false, + UserMetadata: map[string]string{ + "Content-MD5": "acbd18db4cc2f85cedef654fccc4a4d8", // md5("foo") + }, + } + } + + // Seed random based on current time. + rand.Seed(time.Now().Unix()) + + // Instantiate new minio client object. + c, err := minio.New(os.Getenv(serverEndpoint), + &minio.Options{ + Creds: credentials.NewStaticV2(os.Getenv(accessKey), os.Getenv(secretKey), ""), + Secure: mustParseBool(os.Getenv(enableHTTPS)), + }) + if err != nil { + logError(testName, function, args, startTime, "", "MinIO client v2 object creation failed", err) + return + } + + // Enable tracing, write to stderr. + // c.TraceOn(os.Stderr) + + // Set user agent. + c.SetAppInfo("MinIO-go-FunctionalTest", "0.1.0") + + // Generate a new random bucket name. + bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") + args["bucketName"] = bucketName + + // Make a new bucket. + err = c.MakeBucket(context.Background(), bucketName, minio.MakeBucketOptions{Region: "us-east-1"}) + if err != nil { + logError(testName, function, args, startTime, "", "MakeBucket failed", err) + return + } + + defer cleanupBucket(bucketName, c) + + objectName := bucketName + "unique" + args["objectName"] = objectName + + // Upload an object. + _, err = c.PutObject(context.Background(), bucketName, objectName, bytes.NewReader([]byte("foo")), 3, args["opts"]) + if err != nil { + logError(testName, function, args, startTime, "", "PutObjectContentMD5 failed", err) + return + } + + successLogger(testName, function, args, startTime).Info() +} + // Test expected error cases func testComposeObjectErrorCases() { // initialize logging params diff --git a/utils.go b/utils.go index 6a93561ea..686ef6ebd 100644 --- a/utils.go +++ b/utils.go @@ -467,6 +467,7 @@ var supportedHeaders = map[string]bool{ "content-encoding": true, "content-disposition": true, "content-language": true, + "content-md5": true, "x-amz-website-redirect-location": true, "x-amz-object-lock-mode": true, "x-amz-metadata-directive": true,