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.
This commit is contained in:
Harshavardhana 2023-07-22 07:19:43 -07:00 committed by GitHub
parent e1094dde08
commit 7764f4a8e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 22 additions and 15 deletions

View File

@ -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}
}
}
}

View File

@ -38,6 +38,7 @@ import (
const (
copyDirective = "COPY"
replaceDirective = "REPLACE"
accessDirective = "ACCESS"
)
// Parses location constraint from the incoming reader.

View File

@ -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

View File

@ -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