diff --git a/pkg/api/controller.go b/pkg/api/controller.go index 94f15297763..90330c9ec40 100644 --- a/pkg/api/controller.go +++ b/pkg/api/controller.go @@ -2766,6 +2766,7 @@ func (c *Controller) UploadObject(w http.ResponseWriter, r *http.Request, reposi PhysicalAddress: qk.Format(), SizeBytes: swag.Int64(blob.Size), ContentType: &contentType, + Metadata: &apigen.ObjectUserMetadata{AdditionalProperties: meta}, } writeResponse(w, r, http.StatusCreated, response) } @@ -2898,6 +2899,13 @@ func (c *Controller) CopyObject(w http.ResponseWriter, r *http.Request, body api return } + var metadata map[string]string + if entry.Metadata != nil { + metadata = entry.Metadata + } else { + metadata = map[string]string{} + } + response := apigen.ObjectStats{ Checksum: entry.Checksum, Mtime: entry.CreationDate.Unix(), @@ -2906,6 +2914,7 @@ func (c *Controller) CopyObject(w http.ResponseWriter, r *http.Request, body api PhysicalAddress: qk.Format(), SizeBytes: swag.Int64(entry.Size), ContentType: swag.String(entry.ContentType), + Metadata: &apigen.ObjectUserMetadata{AdditionalProperties: metadata}, } writeResponse(w, r, http.StatusCreated, response) } @@ -4023,9 +4032,16 @@ func (c *Controller) StatObject(w http.ResponseWriter, r *http.Request, reposito SizeBytes: swag.Int64(entry.Size), ContentType: swag.String(entry.ContentType), } + + // add metadata if requested + var metadata map[string]string if (params.UserMetadata == nil || *params.UserMetadata) && entry.Metadata != nil { - objStat.Metadata = &apigen.ObjectUserMetadata{AdditionalProperties: entry.Metadata} + metadata = entry.Metadata + } else { + metadata = map[string]string{} } + objStat.Metadata = &apigen.ObjectUserMetadata{AdditionalProperties: metadata} + code := http.StatusOK if entry.Expired { code = http.StatusGone diff --git a/pkg/api/controller_test.go b/pkg/api/controller_test.go index 909aafadefc..f87e35d50d9 100644 --- a/pkg/api/controller_test.go +++ b/pkg/api/controller_test.go @@ -357,8 +357,8 @@ func TestController_LogCommitsParallelHandler(t *testing.T) { } var g multierror.Group - for path, logRef := range commitsToLook { - objects := []string{path} + for objPath, logRef := range commitsToLook { + objects := []string{objPath} params := &apigen.LogCommitsParams{Objects: &objects} log := logRef g.Go(func() error { @@ -1452,10 +1452,10 @@ func TestController_CreateBranchHandler(t *testing.T) { if len(reference) == 0 { t.Fatalf("branch %s creation got no reference", newBranchName) } - const path = "some/path" + const objPath = "some/path" const content = "hello world!" - uploadResp, err := uploadObjectHelper(t, ctx, clt, path, strings.NewReader(content), repo, newBranchName) + uploadResp, err := uploadObjectHelper(t, ctx, clt, objPath, strings.NewReader(content), repo, newBranchName) verifyResponseOK(t, uploadResp, err) if _, err := deps.catalog.Commit(ctx, repo, "main2", "commit 1", "some_user", nil, nil, nil); err != nil { @@ -1467,7 +1467,7 @@ func TestController_CreateBranchHandler(t *testing.T) { if len(results) != 1 { t.Fatalf("unexpected length of results: %d", len(results)) } - if results[0].Path != path { + if results[0].Path != objPath { t.Fatalf("wrong result: %s", results[0].Path) } }) @@ -1581,8 +1581,8 @@ func TestController_DiffRefsHandler(t *testing.T) { t.Fatalf("branch %s creation got no reference", newBranchName) } const prefix = "some/" - const path = "path" - const fullPath = prefix + path + const objPath = "path" + const fullPath = prefix + objPath const content = "hello world!" uploadResp, err := uploadObjectHelper(t, ctx, clt, fullPath, strings.NewReader(content), repoName, newBranchName) @@ -1841,6 +1841,27 @@ func TestController_ObjectsStatObjectHandler(t *testing.T) { t.Fatal(err) } + t.Run("object_stat_no_metadata", func(t *testing.T) { + const objPath = "foo/bar-no-metadata" + entry := catalog.DBEntry{ + Path: objPath, + PhysicalAddress: "this_is_bars_address", + CreationDate: time.Now(), + Size: 666, + Checksum: "this_is_a_checksum", + } + testutil.Must(t, deps.catalog.CreateEntry(ctx, repo, "main", entry)) + + resp, err := clt.StatObjectWithResponse(ctx, repo, "main", &apigen.StatObjectParams{Path: objPath}) + verifyResponseOK(t, resp, err) + if resp.JSON200 == nil { + t.Fatalf("expected to get back object stats, got status %s", resp.Status()) + } + if resp.JSON200.Metadata == nil { + t.Fatal("expected to not get back empty user-defined metadata, got nil") + } + }) + t.Run("get object stats", func(t *testing.T) { entry := catalog.DBEntry{ Path: "foo/bar", @@ -1879,8 +1900,8 @@ func TestController_ObjectsStatObjectHandler(t *testing.T) { resp, err = clt.StatObjectWithResponse(ctx, repo, "main", &apigen.StatObjectParams{Path: "foo/bar", UserMetadata: &getUserMetadata}) verifyResponseOK(t, resp, err) objectStatsNoMetadata := resp.JSON200 - if objectStatsNoMetadata.Metadata != nil { - t.Fatalf("expected to not get back user-defined metadata, got %+v", objectStatsNoMetadata.Metadata.AdditionalProperties) + if objectStatsNoMetadata.Metadata == nil || len(objectStatsNoMetadata.Metadata.AdditionalProperties) != 0 { + t.Fatalf("expected to not get back empty user-defined metadata, got %+v", objectStatsNoMetadata.Metadata.AdditionalProperties) } }) @@ -3793,8 +3814,8 @@ func TestController_PrepareGarbageCollectionUncommitted(t *testing.T) { testutil.Must(t, err) const items = 3 for i := 0; i < items; i++ { - path := fmt.Sprintf("uncommitted/obj%d", i) - uploadResp, err := uploadObjectHelper(t, ctx, clt, path, strings.NewReader(path), repo, "main") + objPath := fmt.Sprintf("uncommitted/obj%d", i) + uploadResp, err := uploadObjectHelper(t, ctx, clt, objPath, strings.NewReader(objPath), repo, "main") verifyResponseOK(t, uploadResp, err) } verifyPrepareGarbageCollection(t, repo, 1, true) @@ -3806,8 +3827,8 @@ func TestController_PrepareGarbageCollectionUncommitted(t *testing.T) { testutil.Must(t, err) const items = 3 for i := 0; i < items; i++ { - path := fmt.Sprintf("committed/obj%d", i) - uploadResp, err := uploadObjectHelper(t, ctx, clt, path, strings.NewReader(path), repo, "main") + objPath := fmt.Sprintf("committed/obj%d", i) + uploadResp, err := uploadObjectHelper(t, ctx, clt, objPath, strings.NewReader(objPath), repo, "main") verifyResponseOK(t, uploadResp, err) } if _, err := deps.catalog.Commit(ctx, repo, "main", "committed objects", "some_user", nil, nil, nil); err != nil { @@ -3822,14 +3843,14 @@ func TestController_PrepareGarbageCollectionUncommitted(t *testing.T) { testutil.Must(t, err) const items = 3 for i := 0; i < items; i++ { - path := fmt.Sprintf("uncommitted/obj%d", i) - uploadResp, err := uploadObjectHelper(t, ctx, clt, path, strings.NewReader(path), repo, "main") + objPath := fmt.Sprintf("uncommitted/obj%d", i) + uploadResp, err := uploadObjectHelper(t, ctx, clt, objPath, strings.NewReader(objPath), repo, "main") verifyResponseOK(t, uploadResp, err) copyResp, err := clt.CopyObjectWithResponse(ctx, repo, "main", &apigen.CopyObjectParams{DestPath: fmt.Sprintf("copy/obj%d", i)}, apigen.CopyObjectJSONRequestBody{ - SrcPath: path, + SrcPath: objPath, }) verifyResponseOK(t, copyResp, err) }