Merge pull request #1721 from versity/sis/precondition-ifmatch-obj-not-exist

fix: return NoSuchKey if a precondition header is present and object doesn't exist in PutObject, CompleteMultipartUpload
This commit is contained in:
Ben McClelland
2025-12-31 00:32:02 -08:00
committed by GitHub
4 changed files with 23 additions and 20 deletions

View File

@@ -2085,8 +2085,6 @@ func (az *Azure) evaluateWritePreconditions(ctx context.Context, bucket, object,
return nil
}
// call HeadObject to evaluate preconditions
// if object doesn't exist, move forward with the object creation
// otherwise return the error
_, err := az.HeadObject(ctx, &s3.HeadObjectInput{
Bucket: bucket,
Key: object,
@@ -2096,11 +2094,8 @@ func (az *Azure) evaluateWritePreconditions(ctx context.Context, bucket, object,
if errors.Is(err, s3err.GetAPIError(s3err.ErrNotModified)) {
return s3err.GetAPIError(s3err.ErrPreconditionFailed)
}
if err != nil && !errors.Is(err, s3err.GetAPIError(s3err.ErrNoSuchKey)) {
return err
}
return nil
return err
}
func getAclFromMetadata(meta map[string]*string, key key) (*auth.ACL, error) {

View File

@@ -1473,6 +1473,9 @@ func (p *Posix) CompleteMultipartUploadWithCopy(ctx context.Context, input *s3.C
}
b, err := p.meta.RetrieveAttribute(nil, bucket, object, etagkey)
if errors.Is(err, fs.ErrNotExist) && (input.IfMatch != nil || input.IfNoneMatch != nil) {
return s3response.CompleteMultipartUploadResult{}, "", s3err.GetAPIError(s3err.ErrNoSuchKey)
}
if err == nil {
err = backend.EvaluateMatchPreconditions(string(b), input.IfMatch, input.IfNoneMatch)
if err != nil {
@@ -2913,6 +2916,9 @@ func (p *Posix) PutObjectWithPostFunc(ctx context.Context, po s3response.PutObje
// evaluate preconditions
etagBytes, err := p.meta.RetrieveAttribute(nil, *po.Bucket, *po.Key, etagkey)
if errors.Is(err, fs.ErrNotExist) && (po.IfMatch != nil || po.IfNoneMatch != nil) {
return s3response.PutObjectOutput{}, s3err.GetAPIError(s3err.ErrNoSuchKey)
}
if err == nil {
err := backend.EvaluateMatchPreconditions(string(etagBytes), po.IfMatch, po.IfNoneMatch)
if err != nil {

View File

@@ -1377,6 +1377,7 @@ func CompleteMultipartUpload_conditional_writes(s *S3Conf) error {
var etagTrimmed string
incorrectEtag := getPtr("incorrect_etag")
errPrecond := s3err.GetAPIError(s3err.ErrPreconditionFailed)
errNoSuchKey := s3err.GetAPIError(s3err.ErrNoSuchKey)
for i, test := range []struct {
obj string
@@ -1393,13 +1394,13 @@ func CompleteMultipartUpload_conditional_writes(s *S3Conf) error {
{obj, nil, incorrectEtag, nil},
{obj, nil, etag, errPrecond},
{obj, nil, nil, nil},
// should ignore the precondition headers if
// an object with the given name doesn't exist
{"obj-1", incorrectEtag, etag, nil},
{"obj-2", etag, etag, nil},
{"obj-3", etag, incorrectEtag, nil},
{"obj-4", incorrectEtag, nil, nil},
{"obj-5", nil, etag, nil},
// should return NoSuchKey error, if any precondition
// header is present, but object doesn't exist
{"obj-1", incorrectEtag, etag, errNoSuchKey},
{"obj-2", etag, etag, errNoSuchKey},
{"obj-3", etag, incorrectEtag, errNoSuchKey},
{"obj-4", incorrectEtag, nil, errNoSuchKey},
{"obj-5", nil, etag, errNoSuchKey},
// precondtion headers without quotes
{obj, &etagTrimmed, nil, nil},

View File

@@ -316,6 +316,7 @@ func PutObject_conditional_writes(s *S3Conf) error {
etagTrimmed := strings.Trim(*etag, `"`)
incorrectEtag := getPtr("incorrect_etag")
errPrecond := s3err.GetAPIError(s3err.ErrPreconditionFailed)
errNoSuchKey := s3err.GetAPIError(s3err.ErrNoSuchKey)
for i, test := range []struct {
obj string
@@ -340,13 +341,13 @@ func PutObject_conditional_writes(s *S3Conf) error {
{obj, incorrectEtag, &etagTrimmed, errPrecond},
{obj, nil, &etagTrimmed, errPrecond},
// should ignore the precondition headers if
// an object with the given name doesn't exist
{"obj-1", incorrectEtag, etag, nil},
{"obj-2", etag, etag, nil},
{"obj-3", etag, incorrectEtag, nil},
{"obj-4", incorrectEtag, nil, nil},
{"obj-5", nil, etag, nil},
// should return NoSuchKey error, if any precondition
// header is present, but object doesn't exist
{"obj-1", incorrectEtag, etag, errNoSuchKey},
{"obj-2", etag, etag, errNoSuchKey},
{"obj-3", etag, incorrectEtag, errNoSuchKey},
{"obj-4", incorrectEtag, nil, errNoSuchKey},
{"obj-5", nil, etag, errNoSuchKey},
} {
res, err := putObjectWithData(0, &s3.PutObjectInput{
Bucket: &bucket,