mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-09-09 01:26:13 +00:00
s3api: fix combined conditional header evaluation per RFC 7232
Per RFC 7232: - Section 3.4: If-Unmodified-Since MUST be ignored when If-Match is present (If-Match is the more accurate replacement) - Section 3.3: If-Modified-Since MUST be ignored when If-None-Match is present (If-None-Match is the more accurate replacement) Previously, all four conditional headers were evaluated independently. This caused incorrect 412 responses when If-Match succeeded but If-Unmodified-Since failed (should return 200 per AWS S3 behavior). Fix applied to both validateConditionalHeadersForReads (GET/HEAD) and validateConditionalHeaders (PUT) paths. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
f323118170
commit
d73c5f40f3
@@ -1658,7 +1658,11 @@ func (s3a *S3ApiServer) validateConditionalHeaders(r *http.Request, headers cond
|
||||
objectExists := entry != nil
|
||||
|
||||
// For PUT requests, all specified conditions must be met.
|
||||
// The evaluation order follows AWS S3 behavior for consistency.
|
||||
// The evaluation order follows RFC 7232 Section 6 and AWS S3 behavior:
|
||||
// 1. If-Match
|
||||
// 2. If-Unmodified-Since (ignored when If-Match is present, per RFC 7232 Section 3.4)
|
||||
// 3. If-None-Match
|
||||
// 4. If-Modified-Since (ignored when If-None-Match is present, per RFC 7232 Section 3.3)
|
||||
|
||||
// 1. Check If-Match
|
||||
if headers.ifMatch != "" {
|
||||
@@ -1679,7 +1683,9 @@ func (s3a *S3ApiServer) validateConditionalHeaders(r *http.Request, headers cond
|
||||
}
|
||||
|
||||
// 2. Check If-Unmodified-Since
|
||||
if !headers.ifUnmodifiedSince.IsZero() {
|
||||
// Per RFC 7232 Section 3.4: "A recipient MUST ignore If-Unmodified-Since
|
||||
// if the request contains an If-Match header field"
|
||||
if !headers.ifUnmodifiedSince.IsZero() && headers.ifMatch == "" {
|
||||
if objectExists {
|
||||
if entry.Attributes != nil {
|
||||
objectModTime := time.Unix(entry.Attributes.Mtime, 0)
|
||||
@@ -1713,7 +1719,9 @@ func (s3a *S3ApiServer) validateConditionalHeaders(r *http.Request, headers cond
|
||||
}
|
||||
|
||||
// 4. Check If-Modified-Since
|
||||
if !headers.ifModifiedSince.IsZero() {
|
||||
// Per RFC 7232 Section 3.3: "A recipient MUST ignore If-Modified-Since
|
||||
// if the request contains an If-None-Match header field"
|
||||
if !headers.ifModifiedSince.IsZero() && headers.ifNoneMatch == "" {
|
||||
if objectExists {
|
||||
if entry.Attributes != nil {
|
||||
objectModTime := time.Unix(entry.Attributes.Mtime, 0)
|
||||
@@ -1802,7 +1810,11 @@ func (s3a *S3ApiServer) validateConditionalHeadersForReads(r *http.Request, head
|
||||
}
|
||||
|
||||
// Object exists - check all conditions
|
||||
// The evaluation order follows AWS S3 behavior for consistency.
|
||||
// The evaluation order follows RFC 7232 Section 6 and AWS S3 behavior:
|
||||
// 1. If-Match
|
||||
// 2. If-Unmodified-Since (ignored when If-Match is present, per RFC 7232 Section 3.4)
|
||||
// 3. If-None-Match
|
||||
// 4. If-Modified-Since (ignored when If-None-Match is present, per RFC 7232 Section 3.3)
|
||||
|
||||
// 1. Check If-Match (412 Precondition Failed if fails)
|
||||
if headers.ifMatch != "" {
|
||||
@@ -1821,7 +1833,9 @@ func (s3a *S3ApiServer) validateConditionalHeadersForReads(r *http.Request, head
|
||||
}
|
||||
|
||||
// 2. Check If-Unmodified-Since (412 Precondition Failed if fails)
|
||||
if !headers.ifUnmodifiedSince.IsZero() {
|
||||
// Per RFC 7232 Section 3.4: "A recipient MUST ignore If-Unmodified-Since
|
||||
// if the request contains an If-Match header field"
|
||||
if !headers.ifUnmodifiedSince.IsZero() && headers.ifMatch == "" {
|
||||
objectModTime := time.Unix(entry.Attributes.Mtime, 0)
|
||||
if objectModTime.After(headers.ifUnmodifiedSince) {
|
||||
glog.V(3).Infof("validateConditionalHeadersForReads: If-Unmodified-Since failed - object modified after %s", r.Header.Get(s3_constants.IfUnmodifiedSince))
|
||||
@@ -1848,7 +1862,9 @@ func (s3a *S3ApiServer) validateConditionalHeadersForReads(r *http.Request, head
|
||||
}
|
||||
|
||||
// 4. Check If-Modified-Since (304 Not Modified if fails)
|
||||
if !headers.ifModifiedSince.IsZero() {
|
||||
// Per RFC 7232 Section 3.3: "A recipient MUST ignore If-Modified-Since
|
||||
// if the request contains an If-None-Match header field"
|
||||
if !headers.ifModifiedSince.IsZero() && headers.ifNoneMatch == "" {
|
||||
objectModTime := time.Unix(entry.Attributes.Mtime, 0)
|
||||
if !objectModTime.After(headers.ifModifiedSince) {
|
||||
// Use production getObjectETag method
|
||||
|
||||
Reference in New Issue
Block a user