mirror of
https://github.com/versity/versitygw.git
synced 2026-04-28 00:06:54 +00:00
feat: adds x-amz-object-size in PutObject response headers
Closes #1518 Adds the `x-amz-object-size` header to the `PutObject` response, indicating the size of the uploaded object. This change is applied to the POSIX, Azure, and S3 proxy backends.
This commit is contained in:
@@ -367,6 +367,7 @@ func (az *Azure) PutObject(ctx context.Context, po s3response.PutObjectInput) (s
|
||||
|
||||
return s3response.PutObjectOutput{
|
||||
ETag: convertAzureEtag(uploadResp.ETag),
|
||||
Size: po.ContentLength,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -2796,6 +2796,7 @@ func (p *Posix) PutObject(ctx context.Context, po s3response.PutObjectInput) (s3
|
||||
// for directory object no version is created
|
||||
return s3response.PutObjectOutput{
|
||||
ETag: emptyMD5,
|
||||
Size: &contentLength,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -2848,6 +2849,8 @@ func (p *Posix) PutObject(ctx context.Context, po s3response.PutObjectInput) (s3
|
||||
}
|
||||
defer f.cleanup()
|
||||
|
||||
objsize := f.size
|
||||
|
||||
hash := md5.New()
|
||||
rdr := io.TeeReader(po.Body, hash)
|
||||
|
||||
@@ -2984,7 +2987,6 @@ func (p *Posix) PutObject(ctx context.Context, po s3response.PutObjectInput) (s3
|
||||
return s3response.PutObjectOutput{}, fmt.Errorf("set versionId attr: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
err = f.link()
|
||||
if errors.Is(err, syscall.EEXIST) {
|
||||
return s3response.PutObjectOutput{
|
||||
@@ -3042,6 +3044,7 @@ func (p *Posix) PutObject(ctx context.Context, po s3response.PutObjectInput) (s3
|
||||
ChecksumSHA1: checksum.SHA1,
|
||||
ChecksumSHA256: checksum.SHA256,
|
||||
ChecksumCRC64NVME: checksum.CRC64NVME,
|
||||
Size: &objsize,
|
||||
ChecksumType: checksum.Type,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -938,6 +938,7 @@ func (s *S3Proxy) PutObject(ctx context.Context, input s3response.PutObjectInput
|
||||
ChecksumCRC64NVME: output.ChecksumCRC64NVME,
|
||||
ChecksumSHA1: output.ChecksumSHA1,
|
||||
ChecksumSHA256: output.ChecksumSHA256,
|
||||
Size: output.Size,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -725,6 +725,7 @@ func (c S3ApiController) PutObject(ctx *fiber.Ctx) (*Response, error) {
|
||||
"x-amz-checksum-sha256": res.ChecksumSHA256,
|
||||
"x-amz-checksum-type": utils.ConvertToStringPtr(res.ChecksumType),
|
||||
"x-amz-version-id": &res.VersionID,
|
||||
"x-amz-object-size": utils.ConvertPtrToStringPtr(res.Size),
|
||||
},
|
||||
MetaOpts: &MetaOptions{
|
||||
ContentLength: contentLength,
|
||||
|
||||
@@ -1036,6 +1036,7 @@ func TestS3ApiController_CopyObject(t *testing.T) {
|
||||
func TestS3ApiController_PutObject(t *testing.T) {
|
||||
str := ""
|
||||
emptyStringPtr := &str
|
||||
objSize := int64(120)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -1148,6 +1149,7 @@ func TestS3ApiController_PutObject(t *testing.T) {
|
||||
"x-amz-checksum-sha256": nil,
|
||||
"x-amz-checksum-type": nil,
|
||||
"x-amz-version-id": emptyStringPtr,
|
||||
"x-amz-object-size": nil,
|
||||
},
|
||||
MetaOpts: &MetaOptions{
|
||||
BucketOwner: "root",
|
||||
@@ -1188,6 +1190,7 @@ func TestS3ApiController_PutObject(t *testing.T) {
|
||||
ChecksumCRC64NVME: utils.GetStringPtr("crc64nvme"),
|
||||
ChecksumType: types.ChecksumTypeComposite,
|
||||
VersionID: "versionId",
|
||||
Size: &objSize,
|
||||
},
|
||||
},
|
||||
output: testOutput{
|
||||
@@ -1201,6 +1204,7 @@ func TestS3ApiController_PutObject(t *testing.T) {
|
||||
"x-amz-checksum-sha256": utils.GetStringPtr("sha256"),
|
||||
"x-amz-checksum-type": utils.GetStringPtr(string(types.ChecksumTypeComposite)),
|
||||
"x-amz-version-id": utils.GetStringPtr("versionId"),
|
||||
"x-amz-object-size": utils.ConvertToStringPtr(objSize),
|
||||
},
|
||||
MetaOpts: &MetaOptions{
|
||||
BucketOwner: "root",
|
||||
|
||||
@@ -37,6 +37,7 @@ type PutObjectOutput struct {
|
||||
ChecksumSHA1 *string
|
||||
ChecksumSHA256 *string
|
||||
ChecksumCRC64NVME *string
|
||||
Size *int64
|
||||
ChecksumType types.ChecksumType
|
||||
}
|
||||
|
||||
|
||||
@@ -3418,10 +3418,33 @@ func PutObject_racey_success(s *S3Conf) error {
|
||||
func PutObject_success(s *S3Conf) error {
|
||||
testName := "PutObject_success"
|
||||
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
|
||||
_, err := putObjects(s3client, []string{"my-obj"}, bucket)
|
||||
lgth := int64(100)
|
||||
res, err := putObjectWithData(lgth, &s3.PutObjectInput{
|
||||
Bucket: &bucket,
|
||||
Key: getPtr("my-obj"),
|
||||
}, s3client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// skip the ETag check for azure tests
|
||||
if !s.azureTests {
|
||||
etag, err := calculateEtag(res.data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if getString(res.res.ETag) != etag {
|
||||
return fmt.Errorf("expected ETag to be %s, intead got %s", getString(res.res.ETag), etag)
|
||||
}
|
||||
}
|
||||
if res.res.Size == nil {
|
||||
return fmt.Errorf("unexpected nil object Size")
|
||||
}
|
||||
if *res.res.Size != lgth {
|
||||
return fmt.Errorf("expected the object size to be %v, instead got %v", lgth, *res.res.Size)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package integration
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
@@ -1798,3 +1799,13 @@ func testOPTIONSEdnpoint(s *S3Conf, bucket, origin, method string, headers strin
|
||||
|
||||
return comparePreflightResult(expected, result)
|
||||
}
|
||||
|
||||
func calculateEtag(data []byte) (string, error) {
|
||||
h := md5.New()
|
||||
_, err := h.Write(data)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
dataSum := h.Sum(nil)
|
||||
return fmt.Sprintf("\"%s\"", hex.EncodeToString(dataSum[:])), nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user