Browse Source

s3api: evaluate conditional headers after version resolution

Move conditional header evaluation (If-Match, If-None-Match, etc.) to
after the version resolution step in GetObjectAttributesHandler. This
ensures that when a specific versionId is requested, conditions are
checked against the correct version entry rather than always against
the latest version.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
pull/8504/head
Chris Lu 1 day ago
parent
commit
55c409decf
  1. 44
      weed/s3api/s3api_object_handlers_attributes.go

44
weed/s3api/s3api_object_handlers_attributes.go

@ -105,12 +105,6 @@ func (s3a *S3ApiServer) GetObjectAttributesHandler(w http.ResponseWriter, r *htt
} }
} }
// Process conditional headers
result, handled := s3a.processConditionalHeaders(w, r, bucket, object, "GetObjectAttributesHandler")
if handled {
return
}
// Check for specific version ID // Check for specific version ID
versionId := r.URL.Query().Get("versionId") versionId := r.URL.Query().Get("versionId")
@ -192,19 +186,33 @@ func (s3a *S3ApiServer) GetObjectAttributesHandler(w http.ResponseWriter, r *htt
w.Header().Set("x-amz-version-id", targetVersionId) w.Header().Set("x-amz-version-id", targetVersionId)
} else { } else {
// Non-versioned: reuse entry from conditional check or fetch
if result.Entry != nil {
entry = result.Entry
} else {
entry, err = s3a.fetchObjectEntry(bucket, object)
if err != nil {
s3err.WriteErrorResponse(w, r, s3err.ErrInternalError)
return
}
if entry == nil {
s3err.WriteErrorResponse(w, r, s3err.ErrNoSuchKey)
return
entry, err = s3a.fetchObjectEntry(bucket, object)
if err != nil {
s3err.WriteErrorResponse(w, r, s3err.ErrInternalError)
return
}
if entry == nil {
s3err.WriteErrorResponse(w, r, s3err.ErrNoSuchKey)
return
}
}
// Evaluate conditional headers against the resolved entry (after version resolution)
// This ensures conditions are checked against the correct version, not always the latest
if s3a.hasConditionalHeaders(r) {
headers, errCode := parseConditionalHeaders(r)
if errCode != s3err.ErrNone {
s3err.WriteErrorResponse(w, r, errCode)
return
}
result := s3a.validateConditionalHeadersForReads(r, headers, entry, bucket, object)
if result.ErrorCode != s3err.ErrNone {
glog.V(3).Infof("GetObjectAttributesHandler: Conditional header check failed for %s/%s with error %v", bucket, object, result.ErrorCode)
if result.ErrorCode == s3err.ErrNotModified && result.ETag != "" {
w.Header().Set("ETag", result.ETag)
} }
s3err.WriteErrorResponse(w, r, result.ErrorCode)
return
} }
} }

Loading…
Cancel
Save