From 219a0846d61032308b714dce55a59de2f94c98ca Mon Sep 17 00:00:00 2001 From: Thiago da Silva Date: Thu, 7 Nov 2019 12:04:01 +0200 Subject: [PATCH 1/2] Update documentation and tests on updating Content-Type Newer swift no longer requires a copy in place to update content-type. Updated a bit of the docs and added test to demonstrate the differences in behavior when using ObjectUpdateContentType and ObjectUpdate to update Content-Type Signed-off-by: Thiago da Silva --- swift.go | 13 +++++++------ swift_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/swift.go b/swift.go index cdb79d908..5f103ec3d 100644 --- a/swift.go +++ b/swift.go @@ -2105,10 +2105,10 @@ func (c *Connection) objectBase(container string, objectName string) (info Objec // X-Delete-At or X-Delete-After for expiring objects. // // You cannot use this to change any of the object's other headers -// such as Content-Type, ETag, etc. +// such as ETag, etc. // // Refer to copying an object when you need to update metadata or -// other headers such as Content-Type or CORS headers. +// other headers such as CORS headers. // // May return ObjectNotFound. func (c *Connection) ObjectUpdate(container string, objectName string, h Headers) error { @@ -2175,11 +2175,12 @@ func (c *Connection) ObjectMove(srcContainer string, srcObjectName string, dstCo return c.ObjectDelete(srcContainer, srcObjectName) } -// ObjectUpdateContentType updates the content type of an object +// ObjectUpdateContentType updates the content type of an object while +// keeping current custom metadata. // -// This is a convenience method which calls ObjectCopy -// -// All other metadata is preserved. +// This is a convenience method which calls ObjectCopy, which causes data movement. +// Content-Type can also be updated with ObjectUpdate which updates metadata +// in place, without need of data movement in the cluster. func (c *Connection) ObjectUpdateContentType(container string, objectName string, contentType string) (err error) { h := Headers{"Content-Type": contentType} _, err = c.ObjectCopy(container, objectName, container, objectName, h) diff --git a/swift_test.go b/swift_test.go index be722cefb..865567f1a 100644 --- a/swift_test.go +++ b/swift_test.go @@ -1612,10 +1612,14 @@ func TestObjectMove(t *testing.T) { func TestObjectUpdateContentType(t *testing.T) { c, rollback := makeConnectionWithObjectHeaders(t) defer rollback() + + // to maintain backwards-compatibility update content-type with + // ObjectUpdateContentType, which copies object in place err := c.ObjectUpdateContentType(CONTAINER, OBJECT, "text/potato") if err != nil { t.Fatal(err) } + // Re-read the metadata to see if it is correct _, headers, err := c.Object(CONTAINER, OBJECT) if err != nil { @@ -1624,7 +1628,27 @@ func TestObjectUpdateContentType(t *testing.T) { if headers["Content-Type"] != "text/potato" { t.Error("Didn't change content type") } + + // ObjectUpdateContentType keeps old metadata because copy was used compareMaps(t, headers.ObjectMetadata(), map[string]string{"hello": "1", "potato-salad": "2"}) + + // Now update content-type with ObjectUpdate + // Note, old metadata is lost if not sent again + h := swift.Headers{"Content-Type": "text/sweet-potato", "X-Object-Meta-Sweet-Potato-Salad": "1"} + err = c.ObjectUpdate(CONTAINER, OBJECT, h) + if err != nil { + t.Fatal(err) + } + + // Re-read the metadata to see if it is correct + _, headers, err = c.Object(CONTAINER, OBJECT) + if err != nil { + t.Fatal(err) + } + if headers["Content-Type"] != "text/sweet-potato" { + t.Error("Didn't change content type") + } + compareMaps(t, headers.ObjectMetadata(), map[string]string{"sweet-potato-salad": "1"}) } func TestVersionContainerCreate(t *testing.T) { From 7219895140106e51af9fa11fb9d7979cd93af20e Mon Sep 17 00:00:00 2001 From: Thiago da Silva Date: Wed, 13 Nov 2019 16:37:49 +0200 Subject: [PATCH 2/2] Add new object update test When posting new custom metadata, the previous custom metadata is lost. --- swift_test.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/swift_test.go b/swift_test.go index 865567f1a..881207fb7 100644 --- a/swift_test.go +++ b/swift_test.go @@ -41,6 +41,7 @@ var ( srv *swifttest.SwiftServer m1 = swift.Metadata{"Hello": "1", "potato-Salad": "2"} m2 = swift.Metadata{"hello": "", "potato-salad": ""} + m3 = swift.Metadata{"sweet-potato-salad": "1"} skipVersionTests = false ) @@ -1304,6 +1305,29 @@ func TestObjectUpdate2(t *testing.T) { compareMaps(t, headers.ObjectMetadata(), map[string]string{"hello": "", "potato-salad": ""}) } +func TestObjectUpdate3(t *testing.T) { + c, rollback := makeConnectionWithObjectHeaders(t) + defer rollback() + + // sanity + _, headers, err := c.Object(CONTAINER, OBJECT) + if err != nil { + t.Fatal(err) + } + compareMaps(t, headers.ObjectMetadata(), map[string]string{"hello": "1", "potato-salad": "1"}) + + // update with new headers + err = c.ObjectUpdate(CONTAINER, OBJECT, m3.ObjectHeaders()) + if err != nil { + t.Fatal(err) + } + _, headers, err = c.Object(CONTAINER, OBJECT) + if err != nil { + t.Fatal(err) + } + compareMaps(t, headers.ObjectMetadata(), map[string]string{"sweet-potato-salad": "1"}) +} + func TestContainers(t *testing.T) { c, rollback := makeConnectionWithObjectHeaders(t) defer rollback()