From cc9a86ef08c29c5a0aa69ee6864a07a7f36fb5bd Mon Sep 17 00:00:00 2001 From: upstream Date: Mon, 5 Oct 2026 20:18:49 +0200 Subject: [PATCH] Upstream versity/versitygw state of the touched files before 6c6b14f7e8 --- s3api/router.go | 11 -- s3err/invalid-argument.go | 22 --- tests/integration/ListMultipartUploads.go | 179 ---------------------- tests/integration/general.go | 42 ----- tests/integration/group-tests.go | 4 - tests/test_rest_list_multipart_uploads.sh | 3 + 6 files changed, 3 insertions(+), 258 deletions(-) diff --git a/s3api/router.go b/s3api/router.go index fabeb52..3ec46da 100644 --- a/s3api/router.go +++ b/s3api/router.go @@ -102,17 +102,6 @@ func (sa *S3ApiRouter) Init() { objectRouter := sa.app.Group("/:bucket/*") applyBucketCORS := middlewares.ApplyBucketCORS(sa.be, middlewares.BucketFromPath, sa.corsAllowOrigin) - // '?uploads' together with '?uploadId' is rejected for every - // bucket and object operation - for _, method := range []string{http.MethodGet, http.MethodHead, http.MethodPut, http.MethodPost, http.MethodDelete} { - for _, router := range []fiber.Router{bucketRouter, objectRouter} { - router.Add([]string{method}, "", - middlewares.MatchQueryArgs("uploads", "uploadId"), - controllers.ProcessHandlers(ctrl.HandleErrorRoute(s3err.GetInvalidArgumentErr(s3err.InvalidArgUploadIdWithUploads, "uploadId")), metrics.ActionUndetected, services), - ) - } - } - // PUT bucket operations bucketRouter.Put("", middlewares.MatchQueryArgs("tagging"), diff --git a/s3err/invalid-argument.go b/s3err/invalid-argument.go index 27f992f..e814bfb 100644 --- a/s3err/invalid-argument.go +++ b/s3err/invalid-argument.go @@ -73,15 +73,9 @@ const ( InvalidArgSSECIncompatibleEncryption InvalidArgSSEInvalidEncryptionMethod InvalidArgSSECRequiresTLS - InvalidArgUploadIdWithUploads - InvalidArgBucketRegionEndpoint ) var invalidArgErrResponses = map[InvalidArgErrorCode]InvalidArgumentError{ - InvalidArgBucketRegionEndpoint: { - Description: "Requests with bucket-region specified must be made to the corresponding regional endpoint", - ArgumentName: "bucket-region", - }, InvalidArgMaxBuckets: { Description: "Argument max-buckets must be an integer between 1 and 10000.", ArgumentName: "max-buckets", @@ -218,10 +212,6 @@ var invalidArgErrResponses = map[InvalidArgErrorCode]InvalidArgumentError{ Description: "Invalid uploadId marker", ArgumentName: "upload-id-marker", }, - InvalidArgUploadIdWithUploads: { - Description: "Conflicting query string parameters: uploadId, uploads", - ArgumentName: "ResourceType", - }, InvalidArgCannedAcl: { Description: "", ArgumentName: "x-amz-acl", @@ -389,15 +379,3 @@ func GetInvalidArgObjectOwnership(value string) InvalidArgumentError { Description: fmt.Sprintf("Invalid x-amz-object-ownership header: %s", value), } } - -func GetInvalidArgBucketRegion(value string) InvalidArgumentError { - description := fmt.Sprintf("Argument value %s is not a valid AWS Region", value) - if value == "" { - description = "Argument value is not a valid AWS Region" - } - return InvalidArgumentError{ - ArgumentName: "bucket-region", - // no ArgumentValue is returned for this error - Description: description, - } -} diff --git a/tests/integration/ListMultipartUploads.go b/tests/integration/ListMultipartUploads.go index 18aa159..f163875 100644 --- a/tests/integration/ListMultipartUploads.go +++ b/tests/integration/ListMultipartUploads.go @@ -17,7 +17,6 @@ package integration import ( "context" "fmt" - "net/http" "sort" "strings" "time" @@ -153,57 +152,6 @@ func ListMultipartUploads_max_uploads(s *S3Conf) error { }) } -func ListMultipartUploads_next_markers_not_truncated(s *S3Conf) error { - testName := "ListMultipartUploads_next_markers_not_truncated" - return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { - uploads := []types.MultipartUpload{} - for _, key := range []string{"bar", "baz", "foo"} { - out, err := createMp(s3client, bucket, key) - if err != nil { - return err - } - uploads = append(uploads, types.MultipartUpload{ - UploadId: out.UploadId, - Key: out.Key, - StorageClass: types.StorageClassStandard, - }) - } - last := uploads[len(uploads)-1] - - // a single page still reports the last upload in the next markers, - // with the default max-uploads and with one equal to the upload count - for _, maxUploads := range []*int32{nil, getPtr(int32(len(uploads)))} { - ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) - out, err := s3client.ListMultipartUploads(ctx, &s3.ListMultipartUploadsInput{ - Bucket: &bucket, - MaxUploads: maxUploads, - }) - cancel() - if err != nil { - return err - } - - if out.IsTruncated == nil || *out.IsTruncated { - return fmt.Errorf("expected a non-truncated response") - } - if ok := compareMultipartUploads(out.Uploads, uploads); !ok { - return fmt.Errorf("expected multipart uploads to be %v, instead got %v", - uploads, out.Uploads) - } - if getString(out.NextKeyMarker) != getString(last.Key) { - return fmt.Errorf("expected next-key-marker to be %v, instead got %v", - getString(last.Key), getString(out.NextKeyMarker)) - } - if getString(out.NextUploadIdMarker) != getString(last.UploadId) { - return fmt.Errorf("expected next-upload-id-marker to be %v, instead got %v", - getString(last.UploadId), getString(out.NextUploadIdMarker)) - } - } - - return nil - }) -} - func ListMultipartUploads_exceeding_max_uploads(s *S3Conf) error { testName := "ListMultipartUploads_exceeding_max_uploads" return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { @@ -258,9 +206,6 @@ func ListMultipartUploads_ignore_upload_id_marker(s *S3Conf) error { return fmt.Errorf("expected multipart uploads to be %v, instead got %v", uploads, out.Uploads) } - if getString(out.UploadIdMarker) != "" { - return fmt.Errorf("expected empty upload id marker, instead got %s", getString(out.UploadIdMarker)) - } // should ignore invalid uploaId marker ctx, cancel = context.WithTimeout(context.Background(), shortTimeout) @@ -276,9 +221,6 @@ func ListMultipartUploads_ignore_upload_id_marker(s *S3Conf) error { return fmt.Errorf("expected multipart uploads to be %v, instead got %v", uploads, out.Uploads) } - if getString(out.UploadIdMarker) != "" { - return fmt.Errorf("expected empty upload id marker, instead got %s", getString(out.UploadIdMarker)) - } return nil }) @@ -404,49 +346,6 @@ func ListMultipartUploads_keyMarker_not_from_list(s *S3Conf) error { }) } -func ListMultipartUploads_upload_id_marker_with_key_marker(s *S3Conf) error { - testName := "ListMultipartUploads_upload_id_marker_with_key_marker" - return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { - for _, key := range []string{"bar", "baz", "baz", "foo"} { - _, err := createMp(s3client, bucket, key) - if err != nil { - return err - } - } - - ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) - out, err := s3client.ListMultipartUploads(ctx, &s3.ListMultipartUploadsInput{ - Bucket: &bucket, - }) - cancel() - if err != nil { - return err - } - uploads := out.Uploads - - // key-marker and upload-id-marker of any listed upload - // should continue the listing right after that upload - for i, up := range uploads { - ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) - out, err := s3client.ListMultipartUploads(ctx, &s3.ListMultipartUploadsInput{ - Bucket: &bucket, - KeyMarker: up.Key, - UploadIdMarker: up.UploadId, - }) - cancel() - if err != nil { - return err - } - - if !compareMultipartUploads(uploads[i+1:], out.Uploads) { - return fmt.Errorf("expected the mp list to be %v, instead got %v", uploads[i+1:], out.Uploads) - } - } - - return nil - }) -} - func ListMultipartUploads_delimiter_truncated(s *S3Conf) error { testName := "ListMultipartUploads_delimiter_truncated" return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { @@ -537,60 +436,6 @@ func ListMultipartUploads_delimiter_truncated(s *S3Conf) error { }) } -func ListMultipartUploads_upload_id_marker_truncated(s *S3Conf) error { - testName := "ListMultipartUploads_upload_id_marker_truncated" - return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { - uploads := make([]types.MultipartUpload, 0, 3) - for _, key := range []string{"bar", "baz", "foo"} { - out, err := createMp(s3client, bucket, key) - if err != nil { - return err - } - uploads = append(uploads, types.MultipartUpload{ - Key: out.Key, - UploadId: out.UploadId, - StorageClass: types.StorageClassStandard, - }) - } - - // the listing starts after the first upload, so a page of 1 - // leaves one upload behind and a page of 2 reaches the end - for _, test := range []struct { - maxUploads int32 - expected []types.MultipartUpload - truncated bool - }{ - {1, uploads[1:2], true}, - {2, uploads[1:], false}, - } { - ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) - out, err := s3client.ListMultipartUploads(ctx, &s3.ListMultipartUploadsInput{ - Bucket: &bucket, - KeyMarker: uploads[0].Key, - UploadIdMarker: uploads[0].UploadId, - MaxUploads: &test.maxUploads, - }) - cancel() - if err != nil { - return err - } - - if !compareMultipartUploads(test.expected, out.Uploads) { - return fmt.Errorf("expected the mp list to be %v, instead got %v", test.expected, out.Uploads) - } - if out.IsTruncated == nil { - return fmt.Errorf("unexpected nil is-truncated") - } - if *out.IsTruncated != test.truncated { - return fmt.Errorf("expected is-truncated to be %v with max-uploads %v, instead got %v", - test.truncated, test.maxUploads, *out.IsTruncated) - } - } - - return nil - }) -} - func ListMultipartUploads_prefix(s *S3Conf) error { testName := "ListMultipartUploads_prefix" return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { @@ -734,30 +579,6 @@ func ListMultipartUploads_delimiter_no_matches(s *S3Conf) error { }) } -func ListMultipartUploads_with_upload_id(s *S3Conf) error { - testName := "ListMultipartUploads_with_upload_id" - return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { - out, err := createMp(s3client, bucket, "my-obj") - if err != nil { - return err - } - - req, err := createSignedReq(http.MethodGet, s.endpoint, - fmt.Sprintf("%v?uploads&uploadId=%v", bucket, *out.UploadId), - s.awsID, s.awsSecret, "s3", s.awsRegion, "", nil, time.Now(), nil) - if err != nil { - return err - } - - resp, err := s.httpClient.Do(req) - if err != nil { - return err - } - - return checkHTTPResponseApiErr(resp, s3err.GetInvalidArgumentErr(s3err.InvalidArgUploadIdWithUploads, "uploadId")) - }) -} - func ListMultipartUploads_with_checksums(s *S3Conf) error { testName := "ListMultipartUploads_with_checksums" return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { diff --git a/tests/integration/general.go b/tests/integration/general.go index ba22f10..50ff019 100644 --- a/tests/integration/general.go +++ b/tests/integration/general.go @@ -195,48 +195,6 @@ func RouterCopySourceNotAllowed(s *S3Conf) error { }) } -func RouterUploadsWithUploadId(s *S3Conf) error { - testName := "RouterUploadsWithUploadId" - return actionHandlerNoSetup(s, testName, func(s3client *s3.Client, bucket string) error { - for _, method := range []string{ - http.MethodGet, - http.MethodHead, - http.MethodPut, - http.MethodPost, - http.MethodDelete, - } { - for _, path := range []string{ - "/bucket?uploads&uploadId=something", - "/bucket/object?uploads&uploadId=something", - } { - req, err := http.NewRequest(method, s.endpoint+path, nil) - if err != nil { - return fmt.Errorf("failed to make %s request to %s", method, path) - } - - resp, err := s.httpClient.Do(req) - if err != nil { - return fmt.Errorf("failed to send %s request to %s", method, path) - } - - if method == http.MethodHead { - // for head requests only check the status code - if resp.StatusCode != http.StatusBadRequest { - return fmt.Errorf("expected 400 status code for HEAD %s request, instead got %v", path, resp.StatusCode) - } - continue - } - - if err := checkHTTPResponseApiErr(resp, s3err.GetInvalidArgumentErr(s3err.InvalidArgUploadIdWithUploads, "uploadId")); err != nil { - return fmt.Errorf("%s %s: %w", method, path, err) - } - } - } - - return nil - }) -} - func RouterListVersionsWithKey(s *S3Conf) error { testName := "RouterListVersionsWithKey" return actionHandlerNoSetup(s, testName, func(s3client *s3.Client, bucket string) error { diff --git a/tests/integration/group-tests.go b/tests/integration/group-tests.go index 96789c9..bd053a9 100644 --- a/tests/integration/group-tests.go +++ b/tests/integration/group-tests.go @@ -554,7 +554,6 @@ func TestListMultipartUploads(ts *TestState) { ts.Run(ListMultipartUploads_prefix) ts.Run(ListMultipartUploads_both_delimiter_and_prefix) ts.Run(ListMultipartUploads_delimiter_no_matches) - ts.Run(ListMultipartUploads_with_upload_id) //TODO: remove the condition after implementing checksums in azure if !ts.conf.azureTests { ts.Run(ListMultipartUploads_with_checksums) @@ -2191,7 +2190,6 @@ func TestRouter(ts *TestState) { ts.Run(RouterGetUploadsWithKey) ts.Run(RouterCopySourceNotAllowed) ts.Run(RouterListVersionsWithKey) - ts.Run(RouterUploadsWithUploadId) ts.Run(RouterObjectAnnotationNotImplemented) ts.Run(RouterRenameObjectNotImplemented) ts.Run(RouterObjectTorrentMethodNotAllowed) @@ -3290,7 +3288,6 @@ func GetIntTests() IntTests { "ListMultipartUploads_delimiter_truncated": ListMultipartUploads_delimiter_truncated, "ListMultipartUploads_prefix": ListMultipartUploads_prefix, "ListMultipartUploads_both_delimiter_and_prefix": ListMultipartUploads_both_delimiter_and_prefix, - "ListMultipartUploads_with_upload_id": ListMultipartUploads_with_upload_id, "ListMultipartUploads_with_checksums": ListMultipartUploads_with_checksums, "AbortMultipartUpload_non_existing_bucket": AbortMultipartUpload_non_existing_bucket, "AbortMultipartUpload_incorrect_uploadId": AbortMultipartUpload_incorrect_uploadId, @@ -3795,7 +3792,6 @@ func GetIntTests() IntTests { "RouterGetUploadsWithKey": RouterGetUploadsWithKey, "RouterCopySourceNotAllowed": RouterCopySourceNotAllowed, "RouterListVersionsWithKey": RouterListVersionsWithKey, - "RouterUploadsWithUploadId": RouterUploadsWithUploadId, "RouterObjectAnnotationNotImplemented": RouterObjectAnnotationNotImplemented, "RouterRenameObjectNotImplemented": RouterRenameObjectNotImplemented, "RouterObjectTorrentMethodNotAllowed": RouterObjectTorrentMethodNotAllowed, diff --git a/tests/test_rest_list_multipart_uploads.sh b/tests/test_rest_list_multipart_uploads.sh index 08020b0..6038dad 100644 --- a/tests/test_rest_list_multipart_uploads.sh +++ b/tests/test_rest_list_multipart_uploads.sh @@ -81,6 +81,9 @@ source ./tests/setup.sh # tags: curl,ListMultipartUploads,multipart,uploadId,key-marker @test "REST - ListMultipartUploads - uploadId and key combo work" { + if [ "$DIRECT" != "true" ]; then + skip "https://github.com/versity/versitygw/issues/2149" + fi run setup_bucket_and_files_v3 "$BUCKET_ONE_NAME" 2 assert_success read -r bucket_name test_file_one test_file_two <<< "$output"