Browse Source

header handling

pull/7481/head
chrislu 3 weeks ago
parent
commit
30a6076626
  1. 11
      weed/s3api/s3api_object_handlers.go
  2. 16
      weed/s3api/s3api_object_handlers_copy.go
  3. 10
      weed/s3api/s3api_object_handlers_put.go
  4. 8
      weed/server/filer_server_handlers_write_autochunk.go

11
weed/s3api/s3api_object_handlers.go

@ -1182,7 +1182,16 @@ func (s3a *S3ApiServer) setResponseHeaders(w http.ResponseWriter, entry *filer_p
for k, v := range entry.Extended {
// Skip internal SeaweedFS headers
if !strings.HasPrefix(k, "xattr-") && !s3_constants.IsSeaweedFSInternalHeader(k) {
w.Header()[k] = []string{string(v)}
// Support backward compatibility: migrate old lowercase format to canonical format
// OLD: "x-amz-meta-foo" → NEW: "X-Amz-Meta-foo"
headerKey := k
if strings.HasPrefix(strings.ToLower(k), "x-amz-meta-") && !strings.HasPrefix(k, s3_constants.AmzUserMetaPrefix) {
// Old format detected - normalize to canonical prefix
suffix := strings.ToLower(k[len("x-amz-meta-"):])
headerKey = s3_constants.AmzUserMetaPrefix + suffix
glog.V(4).Infof("Migrating old user metadata header %q to %q in response", k, headerKey)
}
w.Header()[headerKey] = []string{string(v)}
}
}
}

16
weed/s3api/s3api_object_handlers_copy.go

@ -700,15 +700,29 @@ func processMetadataBytes(reqHeader http.Header, existing map[string][]byte, rep
if replaceMeta {
for header, values := range reqHeader {
if strings.HasPrefix(header, s3_constants.AmzUserMetaPrefix) {
// AWS S3 stores user metadata keys in lowercase
// Go's HTTP server canonicalizes headers (e.g., x-amz-meta-foo → X-Amz-Meta-Foo)
// Preserve the canonical prefix "X-Amz-Meta-" but lowercase the user-defined suffix
suffix := strings.ToLower(header[len(s3_constants.AmzUserMetaPrefix):])
normalizedKey := s3_constants.AmzUserMetaPrefix + suffix
for _, value := range values {
metadata[header] = []byte(value)
metadata[normalizedKey] = []byte(value)
}
}
}
} else {
// Copy existing metadata as-is (already normalized during storage)
// Support both old format (x-amz-meta-*) and new format (X-Amz-Meta-*) for backward compatibility
for k, v := range existing {
if strings.HasPrefix(k, s3_constants.AmzUserMetaPrefix) {
// New format (X-Amz-Meta-foo) - copy as-is
metadata[k] = v
} else if strings.HasPrefix(strings.ToLower(k), "x-amz-meta-") {
// Old format (x-amz-meta-foo) - migrate to new format
suffix := strings.ToLower(k[len("x-amz-meta-"):])
normalizedKey := s3_constants.AmzUserMetaPrefix + suffix
metadata[normalizedKey] = v
glog.V(4).Infof("Migrating old user metadata key %q to %q", k, normalizedKey)
}
}
}

10
weed/s3api/s3api_object_handlers_put.go

@ -480,12 +480,14 @@ func (s3a *S3ApiServer) putToFiler(r *http.Request, uploadUrl string, dataReader
// Copy user metadata and standard headers
for k, v := range r.Header {
if len(v) > 0 && len(v[0]) > 0 {
if strings.HasPrefix(k, "X-Amz-Meta-") {
if strings.HasPrefix(k, s3_constants.AmzUserMetaPrefix) {
// AWS S3 stores user metadata keys in lowercase
// Go's HTTP server canonicalizes headers (e.g., x-amz-meta-foo → X-Amz-Meta-Foo)
// but S3 expects lowercase, so convert back to lowercase for storage
lowerKey := strings.ToLower(k)
entry.Extended[lowerKey] = []byte(v[0])
// Preserve the canonical prefix "X-Amz-Meta-" but lowercase the user-defined suffix
// This ensures the key is still detectable via prefix checks elsewhere
suffix := strings.ToLower(k[len(s3_constants.AmzUserMetaPrefix):])
normalizedKey := s3_constants.AmzUserMetaPrefix + suffix
entry.Extended[normalizedKey] = []byte(v[0])
} else if k == "Cache-Control" || k == "Expires" || k == "Content-Disposition" {
entry.Extended[k] = []byte(v[0])
}

8
weed/server/filer_server_handlers_write_autochunk.go

@ -546,10 +546,12 @@ func SaveAmzMetaData(r *http.Request, existing map[string][]byte, isReplace bool
if strings.HasPrefix(header, s3_constants.AmzUserMetaPrefix) {
// AWS S3 stores user metadata keys in lowercase
// Go's HTTP server canonicalizes headers (e.g., x-amz-meta-foo → X-Amz-Meta-Foo)
// but S3 expects lowercase, so convert back to lowercase for storage
lowerHeader := strings.ToLower(header)
// Preserve the canonical prefix "X-Amz-Meta-" but lowercase the user-defined suffix
// This ensures the key is still detectable via prefix checks elsewhere
suffix := strings.ToLower(header[len(s3_constants.AmzUserMetaPrefix):])
normalizedKey := s3_constants.AmzUserMetaPrefix + suffix
for _, value := range values {
metadata[lowerHeader] = []byte(value)
metadata[normalizedKey] = []byte(value)
}
}
}

Loading…
Cancel
Save