* Fix S3 conditional writes with versioning (Issue #8073) Refactors conditional header checks to properly resolve the latest object version when versioning is enabled. This prevents incorrect validation against non-versioned root objects. * Add integration test for S3 conditional writes with versioning (Issue #8073) * Refactor: Propagate internal errors in conditional header checks - Make resolveObjectEntry return errors from isVersioningConfigured - Update checkConditionalHeaders checks to return 500 on internal resolve errors * Refactor: Stricter error handling and test assertions - Propagate internal errors in checkConditionalHeaders*WithGetter functions - Enforce strict 412 PreconditionFailed check in integration test * Perf: Add early return for conditional headers + safety improvements - Add fast path to skip resolveObjectEntry when no conditional headers present - Avoids expensive getLatestObjectVersion retries in common case - Add nil checks before dereferencing pointers in integration test - Fix grammar in test comments - Remove duplicate comment in resolveObjectEntry * Refactor: Use errors.Is for robust ErrNotFound checking - Update checkConditionalHeaders* to use errors.Is(err, filer_pb.ErrNotFound) - Update resolveObjectEntry to use errors.Is for wrapped error compatibility - Remove duplicate comment lines in s3api handlers * Perf: Optimize resolveObjectEntry for conditional checks - Refactor getLatestObjectVersion to doGetLatestObjectVersion supporting variable retries - Use 1-retry path in resolveObjectEntry to avoid exponential backoff latency * Test: Enhance integration test with content verification - Verify actual object content equals expected content after successful conditional write - Add missing io and errors imports to test file * Refactor: Final refinements based on feedback - Optimize header validation by passing parsed headers to avoid redundant parsing - Simplify integration test assertions using require.Error and assert.True - Fix build errors in s3api handler and test imports * Test: Use smithy.APIError for robust error code checking - Replace string-based error checking with structured API error - Add smithy-go import for AWS SDK v2 error handling * Test: Use types.PreconditionFailed and handle io.ReadAll error - Replace smithy.APIError with more specific types.PreconditionFailed - Add proper error handling for io.ReadAll in content verification * Refactor: Use combined error checking and add nil guards - Use smithy.APIError with ErrorCode() for robust error checking - Add nil guards for entry.Attributes before accessing Mtime - Prevents potential panics when Attributes is uninitialized
This commit is contained in:
@@ -398,6 +398,29 @@ func (s3a *S3ApiServer) checkDirectoryObject(bucket, object string) (*filer_pb.E
|
||||
return dirEntry, true, nil
|
||||
}
|
||||
|
||||
// resolveObjectEntry resolves the object entry for conditional checks,
|
||||
// handling versioned buckets by resolving the latest version.
|
||||
func (s3a *S3ApiServer) resolveObjectEntry(bucket, object string) (*filer_pb.Entry, error) {
|
||||
// Check if versioning is configured
|
||||
versioningConfigured, err := s3a.isVersioningConfigured(bucket)
|
||||
if err != nil && !errors.Is(err, filer_pb.ErrNotFound) {
|
||||
glog.Errorf("resolveObjectEntry: error checking versioning config for %s: %v", bucket, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if versioningConfigured {
|
||||
// For versioned buckets, we must use getLatestObjectVersion to correctly
|
||||
// find the latest versioned object (in .versions/) or null version.
|
||||
// Standard getEntry would fail to find objects moved to .versions/.
|
||||
// Use 1 retry (fast path) for conditional checks to avoid backoff latency.
|
||||
return s3a.doGetLatestObjectVersion(bucket, object, 1)
|
||||
}
|
||||
|
||||
// For non-versioned buckets, verify directly
|
||||
bucketDir := s3a.option.BucketsPath + "/" + bucket
|
||||
return s3a.getEntry(bucketDir, object)
|
||||
}
|
||||
|
||||
// serveDirectoryContent serves the content of a directory object directly
|
||||
func (s3a *S3ApiServer) serveDirectoryContent(w http.ResponseWriter, r *http.Request, entry *filer_pb.Entry) {
|
||||
// Defensive nil checks - entry and attributes should never be nil, but guard against it
|
||||
|
||||
Reference in New Issue
Block a user