From c598ee5416e5fe986ebb7b266ae885a801e80830 Mon Sep 17 00:00:00 2001 From: jonaustin09 Date: Tue, 25 Jul 2023 20:28:40 +0400 Subject: [PATCH] fix: Added accept-range, Content-range and x-amz-tagging-count headers in GetObject action response, added test cases for these --- backend/posix/posix.go | 6 ++++++ integration/tests.go | 8 ++++++++ integration/utils.go | 7 +++++++ s3api/controllers/base.go | 13 +++++++++++++ 4 files changed, 34 insertions(+) diff --git a/backend/posix/posix.go b/backend/posix/posix.go index 8d49fc7..a039cc1 100644 --- a/backend/posix/posix.go +++ b/backend/posix/posix.go @@ -1019,6 +1019,7 @@ func (p *Posix) GetObject(input *s3.GetObjectInput, writer io.Writer) (*s3.GetOb bucket := *input.Bucket object := *input.Key acceptRange := *input.Range + var contentRange string _, err := os.Stat(bucket) if errors.Is(err, fs.ErrNotExist) { @@ -1050,6 +1051,10 @@ func (p *Posix) GetObject(input *s3.GetObjectInput, writer io.Writer) (*s3.GetOb return nil, s3err.GetAPIError(s3err.ErrInvalidRequest) } + if acceptRange != "" { + contentRange = fmt.Sprintf("bytes %v-%v/%v", startOffset, startOffset+length-1, fi.Size()) + } + f, err := os.Open(objPath) if errors.Is(err, fs.ErrNotExist) { return nil, s3err.GetAPIError(s3err.ErrNoSuchKey) @@ -1089,6 +1094,7 @@ func (p *Posix) GetObject(input *s3.GetObjectInput, writer io.Writer) (*s3.GetOb LastModified: backend.GetTimePtr(fi.ModTime()), Metadata: userMetaData, TagCount: int32(len(tags)), + ContentRange: &contentRange, }, nil } diff --git a/integration/tests.go b/integration/tests.go index 2602345..f5c8924 100644 --- a/integration/tests.go +++ b/integration/tests.go @@ -1035,6 +1035,14 @@ func TestRangeGet(s *S3Conf) { } defer out.Body.Close() + if getString(out.ContentRange) != fmt.Sprintf("bytes 100-200/%v", datalen) { + failF("%v: expected content range: %v, instead got: %v", testname, fmt.Sprintf("bytes 100-200/%v", datalen), getString(out.ContentRange)) + return + } + if getString(out.AcceptRanges) != rangeString { + failF("%v: expected accept range: %v, instead got: %v", testname, rangeString, getString(out.AcceptRanges)) + } + b, err := io.ReadAll(out.Body) if err != nil { failF("%v: read body %v", testname, err) diff --git a/integration/utils.go b/integration/utils.go index bbdc95b..02f4c43 100644 --- a/integration/utils.go +++ b/integration/utils.go @@ -154,3 +154,10 @@ func execCommand(args ...string) ([]byte, error) { return cmd.CombinedOutput() } + +func getString(str *string) string { + if str == nil { + return "" + } + return *str +} diff --git a/s3api/controllers/base.go b/s3api/controllers/base.go index acfd9a2..84235a3 100644 --- a/s3api/controllers/base.go +++ b/s3api/controllers/base.go @@ -178,6 +178,7 @@ func (c S3ApiController) GetActions(ctx *fiber.Ctx) error { if res.LastModified != nil { lastmod = res.LastModified.Format(timefmt) } + utils.SetResponseHeaders(ctx, []utils.CustomHeader{ { Key: "Content-Length", @@ -203,6 +204,18 @@ func (c S3ApiController) GetActions(ctx *fiber.Ctx) error { Key: "x-amz-storage-class", Value: string(res.StorageClass), }, + { + Key: "Content-Range", + Value: getstring(res.ContentRange), + }, + { + Key: "accept-ranges", + Value: getstring(res.AcceptRanges), + }, + { + Key: "x-amz-tagging-count", + Value: fmt.Sprint(res.TagCount), + }, }) return SendResponse(ctx, err, &MetaOpts{Logger: c.logger, Action: "GetObject", BucketOwner: parsedAcl.Owner}) }