From 7fb3dedeccd04b3600722537f351dbd5e717d37a Mon Sep 17 00:00:00 2001 From: niksis02 Date: Fri, 20 Feb 2026 13:02:51 +0400 Subject: [PATCH] feat: adds `Location`, `x-amz-bucket-arn` response headers in CreateBucket Closes #1873 --- s3api/controllers/bucket-put.go | 14 +++++++++++++- s3api/controllers/bucket-put_test.go | 5 +++++ tests/integration/CreateBucket.go | 25 +++++++++++++++++++++++++ tests/integration/DeleteBucket.go | 22 ---------------------- tests/integration/group-tests.go | 4 ++-- 5 files changed, 45 insertions(+), 25 deletions(-) diff --git a/s3api/controllers/bucket-put.go b/s3api/controllers/bucket-put.go index a568e1fa..d532131f 100644 --- a/s3api/controllers/bucket-put.go +++ b/s3api/controllers/bucket-put.go @@ -632,9 +632,21 @@ func (c S3ApiController) CreateBucket(ctx *fiber.Ctx) (*Response, error) { Tags: body.TagSet, }, }, updAcl) + if err != nil { + return &Response{ + MetaOpts: &MetaOptions{ + BucketOwner: bucketOwner.Access, + }, + }, err + } + return &Response{ MetaOpts: &MetaOptions{ BucketOwner: bucketOwner.Access, }, - }, err + Headers: map[string]*string{ + "Location": utils.GetStringPtr("/" + bucket), + "x-amz-bucket-arn": utils.GetStringPtr(auth.ResourceArnPrefix + bucket), + }, + }, nil } diff --git a/s3api/controllers/bucket-put_test.go b/s3api/controllers/bucket-put_test.go index 00def053..c7308904 100644 --- a/s3api/controllers/bucket-put_test.go +++ b/s3api/controllers/bucket-put_test.go @@ -888,12 +888,17 @@ func TestS3ApiController_CreateBucket(t *testing.T) { locals: map[utils.ContextKey]any{ utils.ContextKeyAccount: adminAcc, }, + bucket: "my-bucket", }, output: testOutput{ response: &Response{ MetaOpts: &MetaOptions{ BucketOwner: adminAcc.Access, }, + Headers: map[string]*string{ + "Location": utils.GetStringPtr("/my-bucket"), + "x-amz-bucket-arn": utils.GetStringPtr("arn:aws:s3:::my-bucket"), + }, }, }, }, diff --git a/tests/integration/CreateBucket.go b/tests/integration/CreateBucket.go index 61e44d67..6eb552c3 100644 --- a/tests/integration/CreateBucket.go +++ b/tests/integration/CreateBucket.go @@ -641,3 +641,28 @@ func CreateBucket_invalid_canned_acl(s *S3Conf) error { return checkSdkApiErr(err, "InvalidArgument") }) } + +func CreateBucket_success(s *S3Conf) error { + testName := "CreateBucket_success" + return actionHandlerNoSetup(s, testName, func(s3client *s3.Client, bucket string) error { + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) + res, err := s3client.CreateBucket(ctx, &s3.CreateBucketInput{ + Bucket: &bucket, + }) + cancel() + if err != nil { + return err + } + + expectedLocation := "/" + bucket + if getString(res.Location) != expectedLocation { + return fmt.Errorf("expected the bucket Location to be %s, instead got %s", expectedLocation, getString(res.Location)) + } + expectedArn := "arn:aws:s3:::" + bucket + if getString(res.BucketArn) != expectedArn { + return fmt.Errorf("expected the bucket arn to be %s, instead got %s", expectedArn, getString(res.BucketArn)) + } + + return teardown(s, bucket) + }) +} diff --git a/tests/integration/DeleteBucket.go b/tests/integration/DeleteBucket.go index c45c1850..7120a7f8 100644 --- a/tests/integration/DeleteBucket.go +++ b/tests/integration/DeleteBucket.go @@ -24,28 +24,6 @@ import ( "github.com/versity/versitygw/s3err" ) -func CreateDeleteBucket_success(s *S3Conf) error { - testName := "CreateBucket_success" - runF(testName) - bucket := getBucketName() - - err := setup(s, bucket) - if err != nil { - failF("%v: %v", testName, err) - return fmt.Errorf("%v: %w", testName, err) - - } - - err = teardown(s, bucket) - if err != nil { - failF("%v: %v", testName, err) - return fmt.Errorf("%v: %w", testName, err) - } - - passF(testName) - return nil -} - func DeleteBucket_non_existing_bucket(s *S3Conf) error { testName := "DeleteBucket_non_existing_bucket" runF(testName) diff --git a/tests/integration/group-tests.go b/tests/integration/group-tests.go index 248b5a57..dd5c3659 100644 --- a/tests/integration/group-tests.go +++ b/tests/integration/group-tests.go @@ -81,7 +81,7 @@ func TestCreateBucket(ts *TestState) { ts.Run(CreateBucket_non_default_acl) ts.Run(CreateBucket_private_canned_acl) ts.Run(CreateBucket_private_canned_acl_bucket_owner_enforced_ownership) - ts.Run(CreateDeleteBucket_success) + ts.Run(CreateBucket_success) ts.Run(CreateBucket_default_object_lock) ts.Run(CreateBucket_invalid_location_constraint) ts.Run(CreateBucket_long_tags) @@ -1246,7 +1246,7 @@ func GetIntTests() IntTests { "CreateBucket_invalid_ownership": CreateBucket_invalid_ownership, "CreateBucket_ownership_with_acl": CreateBucket_ownership_with_acl, "CreateBucket_as_user": CreateBucket_as_user, - "CreateDeleteBucket_success": CreateDeleteBucket_success, + "CreateBucket_success": CreateBucket_success, "CreateBucket_default_acl": CreateBucket_default_acl, "CreateBucket_non_default_acl": CreateBucket_non_default_acl, "CreateBucket_private_canned_acl": CreateBucket_private_canned_acl,