Browse Source

surfacing invalid X-Amz-Tagging as a client error

pull/7523/head
chrislu 2 weeks ago
parent
commit
13b31de902
  1. 27
      weed/s3api/s3_metadata_util.go
  2. 6
      weed/s3api/s3api_object_handlers_multipart.go

27
weed/s3api/s3_metadata_util.go

@ -7,12 +7,14 @@ import (
"github.com/seaweedfs/seaweedfs/weed/glog"
"github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
"github.com/seaweedfs/seaweedfs/weed/s3api/s3err"
)
// ParseS3Metadata extracts S3-specific metadata from HTTP request headers
// This includes: storage class, tags, user metadata, SSE headers, and ACL headers
// Used by S3 API handlers to prepare metadata before saving to filer
func ParseS3Metadata(r *http.Request, existing map[string][]byte, isReplace bool) (metadata map[string][]byte) {
// Returns an S3 error code if tag parsing fails
func ParseS3Metadata(r *http.Request, existing map[string][]byte, isReplace bool) (metadata map[string][]byte, errCode s3err.ErrorCode) {
metadata = make(map[string][]byte)
// Copy existing metadata unless replacing
@ -37,17 +39,18 @@ func ParseS3Metadata(r *http.Request, existing map[string][]byte, isReplace bool
// Use url.ParseQuery for robust parsing and automatic URL decoding
parsedTags, err := url.ParseQuery(tags)
if err != nil {
glog.Errorf("Failed to parse S3 tags '%s': %v", tags, err)
} else {
for key, values := range parsedTags {
// According to S3 spec, if a key is provided multiple times, the last value is used.
// A tag value can be an empty string but not nil.
value := ""
if len(values) > 0 {
value = values[len(values)-1]
}
metadata[s3_constants.AmzObjectTagging+"-"+key] = []byte(value)
// Return proper S3 error instead of silently dropping tags
glog.Warningf("Invalid S3 tag format in header '%s': %v", tags, err)
return nil, s3err.ErrInvalidTag
}
for key, values := range parsedTags {
// According to S3 spec, if a key is provided multiple times, the last value is used.
// A tag value can be an empty string but not nil.
value := ""
if len(values) > 0 {
value = values[len(values)-1]
}
metadata[s3_constants.AmzObjectTagging+"-"+key] = []byte(value)
}
}
@ -83,5 +86,5 @@ func ParseS3Metadata(r *http.Request, existing map[string][]byte, isReplace bool
metadata[s3_constants.ExtAmzAclKey] = []byte(acpGrants)
}
return metadata
return metadata, s3err.ErrNone
}

6
weed/s3api/s3api_object_handlers_multipart.go

@ -65,7 +65,11 @@ func (s3a *S3ApiServer) NewMultipartUploadHandler(w http.ResponseWriter, r *http
}
// Parse S3 metadata from request headers
metadata := ParseS3Metadata(r, nil, false)
metadata, errCode := ParseS3Metadata(r, nil, false)
if errCode != s3err.ErrNone {
s3err.WriteErrorResponse(w, r, errCode)
return
}
for k, v := range metadata {
createMultipartUploadInput.Metadata[k] = aws.String(string(v))
}

Loading…
Cancel
Save