Skip to content

Commit

Permalink
fix: Added the versionId prop in GetObject response, when attempting …
Browse files Browse the repository at this point in the history
…to get the latest object version without specifying the versionId
  • Loading branch information
0x180 committed Sep 27, 2024
1 parent 44d51b7 commit 82592d9
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 9 deletions.
36 changes: 27 additions & 9 deletions backend/posix/posix.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ const (
deleteMarkerKey = "delete-marker"
versionIdKey = "version-id"

nullVersionId = "null"

doFalloc = true
skipFalloc = false
)
Expand Down Expand Up @@ -2444,8 +2446,12 @@ func (p *Posix) GetObject(_ context.Context, input *s3.GetObjectInput) (*s3.GetO
if input.Range == nil {
return nil, s3err.GetAPIError(s3err.ErrInvalidRange)
}
var versionId string
if input.VersionId != nil {
versionId = *input.VersionId
}

if !p.versioningEnabled() && *input.VersionId != "" {
if !p.versioningEnabled() && versionId != "" {
//TODO: Maybe we need to return our custom error here?
return nil, s3err.GetAPIError(s3err.ErrInvalidVersionId)
}
Expand All @@ -2460,7 +2466,7 @@ func (p *Posix) GetObject(_ context.Context, input *s3.GetObjectInput) (*s3.GetO
}

object := *input.Key
if *input.VersionId != "" {
if versionId != "" {
vId, err := p.meta.RetrieveAttribute(bucket, object, versionIdKey)
if errors.Is(err, fs.ErrNotExist) {
return nil, s3err.GetAPIError(s3err.ErrNoSuchKey)
Expand All @@ -2470,20 +2476,20 @@ func (p *Posix) GetObject(_ context.Context, input *s3.GetObjectInput) (*s3.GetO
}
if errors.Is(err, meta.ErrNoSuchKey) {
bucket = filepath.Join(p.versioningDir, bucket)
object = filepath.Join(genObjVersionKey(object), *input.VersionId)
object = filepath.Join(genObjVersionKey(object), versionId)
}

if string(vId) != *input.VersionId {
if string(vId) != versionId {
bucket = filepath.Join(p.versioningDir, bucket)
object = filepath.Join(genObjVersionKey(object), *input.VersionId)
object = filepath.Join(genObjVersionKey(object), versionId)
}
}

objPath := filepath.Join(bucket, object)

fi, err := os.Stat(objPath)
if errors.Is(err, fs.ErrNotExist) {
if *input.VersionId != "" {
if versionId != "" {
return nil, s3err.GetAPIError(s3err.ErrInvalidVersionId)
}
return nil, s3err.GetAPIError(s3err.ErrNoSuchKey)
Expand All @@ -2502,7 +2508,7 @@ func (p *Posix) GetObject(_ context.Context, input *s3.GetObjectInput) (*s3.GetO
return nil, s3err.GetAPIError(s3err.ErrNoSuchKey)
}

if *input.VersionId != "" {
if versionId != "" {
isDelMarker, err := p.isObjDeleteMarker(bucket, object)
if err != nil {
return nil, err
Expand Down Expand Up @@ -2577,10 +2583,22 @@ func (p *Posix) GetObject(_ context.Context, input *s3.GetObjectInput) (*s3.GetO
TagCount: tagCount,
ContentRange: &contentRange,
StorageClass: types.StorageClassStandard,
VersionId: input.VersionId,
VersionId: &versionId,
}, nil
}

// If versioning is configured get the object versionId
if p.versioningEnabled() && versionId == "" {
vId, err := p.meta.RetrieveAttribute(bucket, object, versionIdKey)
if errors.Is(err, meta.ErrNoSuchKey) {
versionId = nullVersionId
} else if err != nil {
return nil, err
}

versionId = string(vId)
}

userMetaData := make(map[string]string)

contentType, contentEncoding := p.loadUserMetaData(bucket, object, userMetaData)
Expand Down Expand Up @@ -2622,7 +2640,7 @@ func (p *Posix) GetObject(_ context.Context, input *s3.GetObjectInput) (*s3.GetO
TagCount: tagCount,
ContentRange: &contentRange,
StorageClass: types.StorageClassStandard,
VersionId: input.VersionId,
VersionId: &versionId,
Body: &backend.FileSectionReadCloser{R: rdr, F: f},
}, nil
}
Expand Down
31 changes: 31 additions & 0 deletions tests/integration/tests.go
Original file line number Diff line number Diff line change
Expand Up @@ -10811,6 +10811,7 @@ func Versioning_GetObject_success(s *S3Conf) error {
return err
}

// Get the object by versionId
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
out, err := s3client.GetObject(ctx, &s3.GetObjectInput{
Bucket: &bucket,
Expand All @@ -10833,12 +10834,42 @@ func Versioning_GetObject_success(s *S3Conf) error {
if err != nil {
return err
}
defer out.Body.Close()

outCsum := sha256.Sum256(bdy)
if outCsum != r.csum {
return fmt.Errorf("incorrect output content")
}

// Get the object without versionId
ctx, cancel = context.WithTimeout(context.Background(), shortTimeout)
out, err = s3client.GetObject(ctx, &s3.GetObjectInput{
Bucket: &bucket,
Key: &obj,
})
cancel()
if err != nil {
return err
}

if *out.ContentLength != dLen {
return fmt.Errorf("expected the object content-length to be %v, instead got %v", dLen, *out.ContentLength)
}
if *out.VersionId != *r.res.VersionId {
return fmt.Errorf("expected the versionId to be %v, instead got %v", *r.res.VersionId, *out.VersionId)
}

bdy, err = io.ReadAll(out.Body)
if err != nil {
return err
}
defer out.Body.Close()

outCsum = sha256.Sum256(bdy)
if outCsum != r.csum {
return fmt.Errorf("incorrect output content")
}

return nil
}, withVersioning())
}
Expand Down

0 comments on commit 82592d9

Please sign in to comment.