From 832371afb14fea6e81a978dee1bb6e468120152c Mon Sep 17 00:00:00 2001 From: niksis02 Date: Fri, 28 Mar 2025 07:27:35 +0400 Subject: [PATCH] fix: Fixes the case for GetObjectAttributes to return InvalidArgument if a single invalid object attribute is provided. Fixes #1000 `GetObjectAttributes` returned `InvalidRequest` instead of `InvalidArgument` with description `Invalid attribute name specified.`. Fixes the logic in `ParseObjectAttributes` to ignore empty values for `X-Amz-Object-Attributes` headers to return `InvalidArgument` if all the specified object attributes are invalid. --- s3api/utils/utils.go | 9 ++++++++- tests/integration/group-tests.go | 2 ++ tests/integration/tests.go | 21 +++++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/s3api/utils/utils.go b/s3api/utils/utils.go index 2bf2f556..00f4a998 100644 --- a/s3api/utils/utils.go +++ b/s3api/utils/utils.go @@ -298,6 +298,9 @@ func ParseObjectAttributes(ctx *fiber.Ctx) (map[s3response.ObjectAttributes]stru var err error ctx.Request().Header.VisitAll(func(key, value []byte) { if string(key) == "X-Amz-Object-Attributes" { + if len(value) == 0 { + return + } oattrs := strings.Split(string(value), ",") for _, a := range oattrs { attr := s3response.ObjectAttributes(a) @@ -310,11 +313,15 @@ func ParseObjectAttributes(ctx *fiber.Ctx) (map[s3response.ObjectAttributes]stru } }) + if err != nil { + return nil, err + } + if len(attrs) == 0 { return nil, s3err.GetAPIError(s3err.ErrObjectAttributesInvalidHeader) } - return attrs, err + return attrs, nil } type objLockCfg struct { diff --git a/tests/integration/group-tests.go b/tests/integration/group-tests.go index 6b2f0e5e..b67d911a 100644 --- a/tests/integration/group-tests.go +++ b/tests/integration/group-tests.go @@ -178,6 +178,7 @@ func TestGetObjectAttributes(s *S3Conf) { GetObjectAttributes_non_existing_object(s) GetObjectAttributes_invalid_attrs(s) GetObjectAttributes_invalid_parent(s) + GetObjectAttributes_invalid_single_attribute(s) GetObjectAttributes_empty_attrs(s) GetObjectAttributes_existing_object(s) //TODO: remove the condition after implementing checksums in azure @@ -868,6 +869,7 @@ func GetIntTests() IntTests { "GetObjectAttributes_non_existing_object": GetObjectAttributes_non_existing_object, "GetObjectAttributes_invalid_attrs": GetObjectAttributes_invalid_attrs, "GetObjectAttributes_invalid_parent": GetObjectAttributes_invalid_parent, + "GetObjectAttributes_invalid_single_attribute": GetObjectAttributes_invalid_single_attribute, "GetObjectAttributes_empty_attrs": GetObjectAttributes_empty_attrs, "GetObjectAttributes_existing_object": GetObjectAttributes_existing_object, "GetObjectAttributes_checksums": GetObjectAttributes_checksums, diff --git a/tests/integration/tests.go b/tests/integration/tests.go index e8ace20f..9e3309ae 100644 --- a/tests/integration/tests.go +++ b/tests/integration/tests.go @@ -3723,6 +3723,27 @@ func GetObjectAttributes_invalid_parent(s *S3Conf) error { }) } +func GetObjectAttributes_invalid_single_attribute(s *S3Conf) error { + testName := "GetObjectAttributes_invalid_single_attribute" + return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { + obj := "my-obj" + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) + _, err := s3client.GetObjectAttributes(ctx, &s3.GetObjectAttributesInput{ + Bucket: &bucket, + Key: &obj, + ObjectAttributes: []types.ObjectAttributes{ + types.ObjectAttributes("invalid_attr"), + }, + }) + cancel() + if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrInvalidObjectAttributes)); err != nil { + return err + } + + return nil + }) +} + func GetObjectAttributes_empty_attrs(s *S3Conf) error { testName := "GetObjectAttributes_empty_attrs" return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {