From 7764f4a8e39c5eda044fa6423dde855e48d79116 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Sat, 22 Jul 2023 07:19:43 -0700 Subject: [PATCH] return tags as part of Head/Get calls (#17635) AWS S3 only returns the number of tag counts, along with that we must return the tags as well to avoid another metadata call to the server. --- cmd/api-headers.go | 12 ++++++++---- cmd/handler-utils.go | 1 + cmd/object-api-interface.go | 1 + cmd/object-api-options.go | 23 ++++++++++++----------- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/cmd/api-headers.go b/cmd/api-headers.go index a3f42a4e4..a71205996 100644 --- a/cmd/api-headers.go +++ b/cmd/api-headers.go @@ -23,11 +23,11 @@ import ( "encoding/xml" "fmt" "net/http" - "net/url" "strconv" "strings" "time" + "github.com/minio/minio-go/v7/pkg/tags" "github.com/minio/minio/internal/crypto" xhttp "github.com/minio/minio/internal/http" "github.com/minio/minio/internal/logger" @@ -140,9 +140,13 @@ func setObjectHeaders(w http.ResponseWriter, objInfo ObjectInfo, rs *HTTPRangeSp // Set tag count if object has tags if len(objInfo.UserTags) > 0 { - tags, _ := url.ParseQuery(objInfo.UserTags) - if len(tags) > 0 { - w.Header()[xhttp.AmzTagCount] = []string{strconv.Itoa(len(tags))} + tags, _ := tags.ParseObjectTags(objInfo.UserTags) + if tags.Count() > 0 { + w.Header()[xhttp.AmzTagCount] = []string{strconv.Itoa(tags.Count())} + if opts.Tagging { + // This is MinIO only extension to return back tags along with the count. + w.Header()[xhttp.AmzObjectTagging] = []string{objInfo.UserTags} + } } } diff --git a/cmd/handler-utils.go b/cmd/handler-utils.go index e9112f74a..0326cbcf4 100644 --- a/cmd/handler-utils.go +++ b/cmd/handler-utils.go @@ -38,6 +38,7 @@ import ( const ( copyDirective = "COPY" replaceDirective = "REPLACE" + accessDirective = "ACCESS" ) // Parses location constraint from the incoming reader. diff --git a/cmd/object-api-interface.go b/cmd/object-api-interface.go index 081fb3d5f..85b4130af 100644 --- a/cmd/object-api-interface.go +++ b/cmd/object-api-interface.go @@ -55,6 +55,7 @@ type ObjectOptions struct { DeleteMarker bool // Is only set in DELETE operations for delete marker replication CheckDMReplicationReady bool // Is delete marker ready to be replicated - set only during HEAD + Tagging bool // Is only in GET/HEAD operations to return tagging metadata along with regular metadata and body. UserDefined map[string]string // only set in case of POST/PUT operations PartNumber int // only useful in case of GetObject/HeadObject diff --git a/cmd/object-api-options.go b/cmd/object-api-options.go index 909713cf5..d4791491f 100644 --- a/cmd/object-api-options.go +++ b/cmd/object-api-options.go @@ -108,21 +108,11 @@ func getOpts(ctx context.Context, r *http.Request, bucket, object string) (Objec } } - deletePrefix := false - if d := r.Header.Get(xhttp.MinIOForceDelete); d != "" { - if b, err := strconv.ParseBool(d); err == nil { - deletePrefix = b - } else { - return opts, err - } - } - // default case of passing encryption headers to backend opts, err = getDefaultOpts(r.Header, false, nil) if err != nil { return opts, err } - opts.DeletePrefix = deletePrefix opts.PartNumber = partNumber opts.VersionID = vid delMarker := strings.TrimSpace(r.Header.Get(xhttp.MinIOSourceDeleteMarker)) @@ -157,7 +147,7 @@ func getOpts(ctx context.Context, r *http.Request, bucket, object string) (Objec } } } - + opts.Tagging = r.Header.Get(xhttp.AmzTagDirective) == accessDirective opts.Versioned = globalBucketVersioningSys.PrefixEnabled(bucket, object) opts.VersionSuspended = globalBucketVersioningSys.PrefixSuspended(bucket, object) return opts, nil @@ -168,6 +158,17 @@ func delOpts(ctx context.Context, r *http.Request, bucket, object string) (opts if err != nil { return opts, err } + + deletePrefix := false + if d := r.Header.Get(xhttp.MinIOForceDelete); d != "" { + if b, err := strconv.ParseBool(d); err == nil { + deletePrefix = b + } else { + return opts, err + } + } + + opts.DeletePrefix = deletePrefix opts.Versioned = globalBucketVersioningSys.PrefixEnabled(bucket, object) // Objects matching prefixes should not leave delete markers, // dramatically reduces namespace pollution while keeping the