From e38c63448d317fc4edb23d7c905c31cbc79c0d6f Mon Sep 17 00:00:00 2001 From: jonaustin09 Date: Mon, 20 May 2024 14:48:02 -0400 Subject: [PATCH] fix: Changed GetObject by range success status code from 200 to 206 --- s3api/controllers/base.go | 16 ++++----- tests/integration/group-tests.go | 2 ++ tests/integration/tests.go | 57 +++++++++++++++++++++++++++++--- tests/integration/utils.go | 7 ++-- 4 files changed, 66 insertions(+), 16 deletions(-) diff --git a/s3api/controllers/base.go b/s3api/controllers/base.go index b5ccb725..e467ecac 100644 --- a/s3api/controllers/base.go +++ b/s3api/controllers/base.go @@ -388,14 +388,6 @@ func (c S3ApiController) GetActions(ctx *fiber.Ctx) error { BucketOwner: parsedAcl.Owner, }) } - if res == nil { - return SendResponse(ctx, fmt.Errorf("get object nil response"), - &MetaOpts{ - Logger: c.logger, - Action: "GetObject", - BucketOwner: parsedAcl.Owner, - }) - } utils.SetMetaHeaders(ctx, res.Metadata) var lastmod string @@ -447,11 +439,17 @@ func (c S3ApiController) GetActions(ctx *fiber.Ctx) error { }) } - return SendResponse(ctx, err, + status := http.StatusOK + if acceptRange != "" { + status = http.StatusPartialContent + } + + return SendResponse(ctx, nil, &MetaOpts{ Logger: c.logger, Action: "GetObject", BucketOwner: parsedAcl.Owner, + Status: status, }) } diff --git a/tests/integration/group-tests.go b/tests/integration/group-tests.go index a070f101..6ef57b57 100644 --- a/tests/integration/group-tests.go +++ b/tests/integration/group-tests.go @@ -138,6 +138,7 @@ func TestGetObject(s *S3Conf) { GetObject_with_meta(s) GetObject_success(s) GetObject_by_range_success(s) + GetObject_by_range_resp_status(s) } func TestListObjects(s *S3Conf) { @@ -525,6 +526,7 @@ func GetIntTests() IntTests { "GetObject_with_meta": GetObject_with_meta, "GetObject_success": GetObject_success, "GetObject_by_range_success": GetObject_by_range_success, + "GetObject_by_range_resp_status": GetObject_by_range_resp_status, "ListObjects_non_existing_bucket": ListObjects_non_existing_bucket, "ListObjects_with_prefix": ListObjects_with_prefix, "ListObject_truncated": ListObject_truncated, diff --git a/tests/integration/tests.go b/tests/integration/tests.go index 2d873704..a8b9965a 100644 --- a/tests/integration/tests.go +++ b/tests/integration/tests.go @@ -2138,7 +2138,7 @@ func DeleteBucket_success_status_code(s *S3Conf) error { return fmt.Errorf("%v: %w", testName, err) } - req, err := createSignedReq(http.MethodDelete, s.endpoint, bucket, s.awsID, s.awsSecret, "s3", s.awsRegion, nil, time.Now()) + req, err := createSignedReq(http.MethodDelete, s.endpoint, bucket, s.awsID, s.awsSecret, "s3", s.awsRegion, nil, time.Now(), nil) if err != nil { failF("%v: %v", testName, err) return fmt.Errorf("%v: %w", testName, err) @@ -2325,7 +2325,7 @@ func DeleteBucketTagging_success_status(s *S3Conf) error { return err } - req, err := createSignedReq(http.MethodDelete, s.endpoint, fmt.Sprintf("%v?tagging", bucket), s.awsID, s.awsSecret, "s3", s.awsRegion, nil, time.Now()) + req, err := createSignedReq(http.MethodDelete, s.endpoint, fmt.Sprintf("%v?tagging", bucket), s.awsID, s.awsSecret, "s3", s.awsRegion, nil, time.Now(), nil) if err != nil { return err } @@ -3152,6 +3152,53 @@ func GetObject_by_range_success(s *S3Conf) error { }) } +func GetObject_by_range_resp_status(s *S3Conf) error { + testName := "GetObject_by_range_resp_status" + return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { + obj, dLen := "my-obj", int64(4000) + _, _, err := putObjectWithData(dLen, &s3.PutObjectInput{ + Bucket: &bucket, + Key: &obj, + }, s3client) + if err != nil { + return err + } + + req, err := createSignedReq( + http.MethodGet, + s.endpoint, + fmt.Sprintf("%v/%v", bucket, obj), + s.awsID, + s.awsSecret, + "s3", + s.awsRegion, + nil, + time.Now(), + map[string]string{ + "Range": "bytes=100-200", + }, + ) + if err != nil { + return err + } + + client := http.Client{ + Timeout: shortTimeout, + } + + resp, err := client.Do(req) + if err != nil { + return err + } + + if resp.StatusCode != http.StatusPartialContent { + return fmt.Errorf("expected response status to be %v, instead got %v", http.StatusPartialContent, resp.StatusCode) + } + + return nil + }) +} + func ListObjects_non_existing_bucket(s *S3Conf) error { testName := "ListObjects_non_existing_bucket" return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { @@ -3580,7 +3627,7 @@ func DeleteObject_success_status_code(s *S3Conf) error { return err } - req, err := createSignedReq(http.MethodDelete, s.endpoint, fmt.Sprintf("%v/%v", bucket, obj), s.awsID, s.awsSecret, "s3", s.awsRegion, nil, time.Now()) + req, err := createSignedReq(http.MethodDelete, s.endpoint, fmt.Sprintf("%v/%v", bucket, obj), s.awsID, s.awsSecret, "s3", s.awsRegion, nil, time.Now(), nil) if err != nil { return err } @@ -4117,7 +4164,7 @@ func DeleteObjectTagging_success_status(s *S3Conf) error { return err } - req, err := createSignedReq(http.MethodDelete, s.endpoint, fmt.Sprintf("%v/%v?tagging", bucket, obj), s.awsID, s.awsSecret, "s3", s.awsRegion, nil, time.Now()) + req, err := createSignedReq(http.MethodDelete, s.endpoint, fmt.Sprintf("%v/%v?tagging", bucket, obj), s.awsID, s.awsSecret, "s3", s.awsRegion, nil, time.Now(), nil) if err != nil { return err } @@ -5170,7 +5217,7 @@ func AbortMultipartUpload_success_status_code(s *S3Conf) error { return err } - req, err := createSignedReq(http.MethodDelete, s.endpoint, fmt.Sprintf("%v/%v?uploadId=%v", bucket, obj, *out.UploadId), s.awsID, s.awsSecret, "s3", s.awsRegion, nil, time.Now()) + req, err := createSignedReq(http.MethodDelete, s.endpoint, fmt.Sprintf("%v/%v?uploadId=%v", bucket, obj, *out.UploadId), s.awsID, s.awsSecret, "s3", s.awsRegion, nil, time.Now(), nil) if err != nil { return err } diff --git a/tests/integration/utils.go b/tests/integration/utils.go index 6dbc1e09..c3dafef6 100644 --- a/tests/integration/utils.go +++ b/tests/integration/utils.go @@ -168,7 +168,7 @@ type authConfig struct { func authHandler(s *S3Conf, cfg *authConfig, handler func(req *http.Request) error) error { runF(cfg.testName) - req, err := createSignedReq(cfg.method, s.endpoint, cfg.path, s.awsID, s.awsSecret, cfg.service, s.awsRegion, cfg.body, cfg.date) + req, err := createSignedReq(cfg.method, s.endpoint, cfg.path, s.awsID, s.awsSecret, cfg.service, s.awsRegion, cfg.body, cfg.date, nil) if err != nil { failF("%v: %v", cfg.testName, err) return fmt.Errorf("%v: %w", cfg.testName, err) @@ -197,7 +197,7 @@ func presignedAuthHandler(s *S3Conf, testName string, handler func(client *s3.Pr return nil } -func createSignedReq(method, endpoint, path, access, secret, service, region string, body []byte, date time.Time) (*http.Request, error) { +func createSignedReq(method, endpoint, path, access, secret, service, region string, body []byte, date time.Time, headers map[string]string) (*http.Request, error) { req, err := http.NewRequest(method, fmt.Sprintf("%v/%v", endpoint, path), bytes.NewReader(body)) if err != nil { return nil, fmt.Errorf("failed to send the request: %w", err) @@ -209,6 +209,9 @@ func createSignedReq(method, endpoint, path, access, secret, service, region str hexPayload := hex.EncodeToString(hashedPayload[:]) req.Header.Set("X-Amz-Content-Sha256", hexPayload) + for key, val := range headers { + req.Header.Add(key, val) + } signErr := signer.SignHTTP(req.Context(), aws.Credentials{AccessKeyID: access, SecretAccessKey: secret}, req, hexPayload, service, region, date) if signErr != nil {