From 82dac3df03a82e8de1763ca95da2cab87b983436 Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Fri, 26 Dec 2025 13:21:15 -0800 Subject: [PATCH] s3: do not persist multi part "Response-Content-Disposition" in request header (#7887) * fix: support standard HTTP headers in S3 multipart upload * fix(s3api): validate standard HTTP headers correctly and avoid persisting Response-Content-Disposition --------- Co-authored-by: steve.wei --- weed/s3api/s3_metadata_util.go | 7 ++----- weed/s3api/s3api_object_handlers_multipart.go | 10 +++++----- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/weed/s3api/s3_metadata_util.go b/weed/s3api/s3_metadata_util.go index b11ce147a..71ef623f9 100644 --- a/weed/s3api/s3_metadata_util.go +++ b/weed/s3api/s3_metadata_util.go @@ -47,11 +47,8 @@ func ParseS3Metadata(r *http.Request, existing map[string][]byte, isReplace bool } } - // Handle Response-Content-Disposition (used in presigned URLs) - // This should be stored as Content-Disposition - if rcd := r.Header.Get("Response-Content-Disposition"); rcd != "" { - metadata["Content-Disposition"] = []byte(rcd) - } + // Do NOT persist Response-Content-Disposition: it is a GET-only + // presigned-download override and must not be stored as upload metadata. // Object tagging if tags := r.Header.Get(s3_constants.AmzObjectTagging); tags != "" { diff --git a/weed/s3api/s3api_object_handlers_multipart.go b/weed/s3api/s3api_object_handlers_multipart.go index 7fcebef38..88e754461 100644 --- a/weed/s3api/s3api_object_handlers_multipart.go +++ b/weed/s3api/s3api_object_handlers_multipart.go @@ -67,16 +67,16 @@ func (s3a *S3ApiServer) NewMultipartUploadHandler(w http.ResponseWriter, r *http } // Validate Cache-Control header format if present - if r.Header.Get("Cache-Control") != "" { - if _, err := cacheobject.ParseRequestCacheControl(r.Header.Get("Cache-Control")); err != nil { - s3err.WriteErrorResponse(w, r, s3err.ErrInvalidDigest) + if cacheControl := r.Header.Get("Cache-Control"); cacheControl != "" { + if _, err := cacheobject.ParseRequestCacheControl(cacheControl); err != nil { + s3err.WriteErrorResponse(w, r, s3err.ErrInvalidRequest) return } } // Validate Expires header format if present - if r.Header.Get("Expires") != "" { - if _, err := time.Parse(http.TimeFormat, r.Header.Get("Expires")); err != nil { + if expires := r.Header.Get("Expires"); expires != "" { + if _, err := time.Parse(http.TimeFormat, expires); err != nil { s3err.WriteErrorResponse(w, r, s3err.ErrMalformedDate) return }