Browse Source

surfacing invalid X-Amz-Tagging as a client error

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

13
weed/s3api/s3_metadata_util.go

@ -7,12 +7,14 @@ import (
"github.com/seaweedfs/seaweedfs/weed/glog" "github.com/seaweedfs/seaweedfs/weed/glog"
"github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants" "github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
"github.com/seaweedfs/seaweedfs/weed/s3api/s3err"
) )
// ParseS3Metadata extracts S3-specific metadata from HTTP request headers // ParseS3Metadata extracts S3-specific metadata from HTTP request headers
// This includes: storage class, tags, user metadata, SSE headers, and ACL 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 // 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) metadata = make(map[string][]byte)
// Copy existing metadata unless replacing // Copy existing metadata unless replacing
@ -37,8 +39,10 @@ func ParseS3Metadata(r *http.Request, existing map[string][]byte, isReplace bool
// Use url.ParseQuery for robust parsing and automatic URL decoding // Use url.ParseQuery for robust parsing and automatic URL decoding
parsedTags, err := url.ParseQuery(tags) parsedTags, err := url.ParseQuery(tags)
if err != nil { if err != nil {
glog.Errorf("Failed to parse S3 tags '%s': %v", tags, err)
} else {
// 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 { for key, values := range parsedTags {
// According to S3 spec, if a key is provided multiple times, the last value is used. // 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. // A tag value can be an empty string but not nil.
@ -49,7 +53,6 @@ func ParseS3Metadata(r *http.Request, existing map[string][]byte, isReplace bool
metadata[s3_constants.AmzObjectTagging+"-"+key] = []byte(value) metadata[s3_constants.AmzObjectTagging+"-"+key] = []byte(value)
} }
} }
}
// User-defined metadata (x-amz-meta-* headers) // User-defined metadata (x-amz-meta-* headers)
for header, values := range r.Header { for header, values := range r.Header {
@ -83,5 +86,5 @@ func ParseS3Metadata(r *http.Request, existing map[string][]byte, isReplace bool
metadata[s3_constants.ExtAmzAclKey] = []byte(acpGrants) 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 // 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 { for k, v := range metadata {
createMultipartUploadInput.Metadata[k] = aws.String(string(v)) createMultipartUploadInput.Metadata[k] = aws.String(string(v))
} }

Loading…
Cancel
Save