From 2c858e292562eec7061723dc1e18d1f3824d2fca Mon Sep 17 00:00:00 2001 From: Andrew Gaul Date: Sun, 24 Nov 2024 19:24:14 -0800 Subject: [PATCH] Add disposition and language to ComposeObject --- fakestorage/object.go | 2 +- fakestorage/object_test.go | 24 ++++++++++++++++++++++++ internal/backend/fs.go | 4 +++- internal/backend/memory.go | 4 +++- internal/backend/storage.go | 2 +- internal/grpc/server.go | 4 ++-- 6 files changed, 34 insertions(+), 6 deletions(-) diff --git a/fakestorage/object.go b/fakestorage/object.go index 441c4ceace..664751ee44 100644 --- a/fakestorage/object.go +++ b/fakestorage/object.go @@ -1262,7 +1262,7 @@ func (s *Server) composeObject(r *http.Request) jsonResponse { sourceNames = append(sourceNames, n.Name) } - backendObj, err := s.backend.ComposeObject(bucketName, sourceNames, destinationObject, composeRequest.Destination.Metadata, composeRequest.Destination.ContentType) + backendObj, err := s.backend.ComposeObject(bucketName, sourceNames, destinationObject, composeRequest.Destination.Metadata, composeRequest.Destination.ContentType, composeRequest.Destination.ContentDisposition, composeRequest.Destination.ContentLanguage) if err != nil { return jsonResponse{ status: http.StatusInternalServerError, diff --git a/fakestorage/object_test.go b/fakestorage/object_test.go index 59f7a8a40f..2ad0976918 100644 --- a/fakestorage/object_test.go +++ b/fakestorage/object_test.go @@ -2126,6 +2126,8 @@ func TestServiceClientComposeObject(t *testing.T) { source1Content = "some content" source2Content = "other content" source3Content = "third test" + contentDisposition = "attachment; filename=\"replaced.txt\"" + contentLanguage = "fr" contentType = "text/plain; charset=utf-8" ) u32Checksum := uint32Checksum([]byte(source1Content)) @@ -2137,6 +2139,8 @@ func TestServiceClientComposeObject(t *testing.T) { ObjectAttrs: ObjectAttrs{ BucketName: "first-bucket", Name: "files/source1.txt", + ContentDisposition: contentDisposition, + ContentLanguage: contentLanguage, ContentType: contentType, Crc32c: checksum.EncodedChecksum(uint32ToBytes(u32Checksum)), Md5Hash: checksum.EncodedHash(hash), @@ -2148,6 +2152,8 @@ func TestServiceClientComposeObject(t *testing.T) { ObjectAttrs: ObjectAttrs{ BucketName: "first-bucket", Name: "files/source2.txt", + ContentDisposition: contentDisposition, + ContentLanguage: contentLanguage, ContentType: contentType, Crc32c: checksum.EncodedChecksum(uint32ToBytes(u32Checksum)), Md5Hash: checksum.EncodedHash(hash), @@ -2159,6 +2165,8 @@ func TestServiceClientComposeObject(t *testing.T) { ObjectAttrs: ObjectAttrs{ BucketName: "first-bucket", Name: "files/source3.txt", + ContentDisposition: contentDisposition, + ContentLanguage: contentLanguage, ContentType: contentType, Crc32c: checksum.EncodedChecksum(uint32ToBytes(u32Checksum)), Md5Hash: checksum.EncodedHash(hash), @@ -2170,6 +2178,8 @@ func TestServiceClientComposeObject(t *testing.T) { ObjectAttrs: ObjectAttrs{ BucketName: "first-bucket", Name: "files/destination.txt", + ContentDisposition: contentDisposition, + ContentLanguage: contentLanguage, ContentType: contentType, Crc32c: checksum.EncodedChecksum(uint32ToBytes(u32Checksum)), Md5Hash: checksum.EncodedHash(hash), @@ -2236,6 +2246,8 @@ func TestServiceClientComposeObject(t *testing.T) { dstObject := client.Bucket(test.bucketName).Object(test.destObjectName) composer := dstObject.ComposerFrom(sourceObjects...) + composer.ContentDisposition = contentDisposition + composer.ContentLanguage = contentLanguage composer.ContentType = contentType composer.Metadata = map[string]string{"baz": "qux"} attrs, err := composer.Run(context.TODO()) @@ -2261,6 +2273,12 @@ func TestServiceClientComposeObject(t *testing.T) { if attrs.CRC32C != expectedChecksum { t.Errorf("wrong checksum in compose object attrs\nwant %d\ngot %d", u32Checksum, attrs.CRC32C) } + if attrs.ContentDisposition != contentDisposition { + t.Errorf("wrong content disposition\nwant %q\ngot %q", contentDisposition, attrs.ContentDisposition) + } + if attrs.ContentLanguage != contentLanguage { + t.Errorf("wrong content language\nwant %q\ngot %q", contentLanguage, attrs.ContentLanguage) + } if attrs.ContentType != contentType { t.Errorf("wrong content type\nwant %q\ngot %q", contentType, attrs.ContentType) } @@ -2286,6 +2304,12 @@ func TestServiceClientComposeObject(t *testing.T) { if expect := checksum.EncodedHash(expectedHash); expect != obj.Md5Hash { t.Errorf("wrong hash on object\nwant %s\ngot %s", expect, obj.Md5Hash) } + if obj.ContentDisposition != contentDisposition { + t.Errorf("wrong content disposition\nwant %q\ngot %q", contentDisposition, obj.ContentDisposition) + } + if obj.ContentLanguage != contentLanguage { + t.Errorf("wrong content language\nwant %q\ngot %q", contentLanguage, obj.ContentLanguage) + } if obj.ContentType != contentType { t.Errorf("wrong content type\nwant %q\ngot %q", contentType, obj.ContentType) } diff --git a/internal/backend/fs.go b/internal/backend/fs.go index 52cbcd1859..e673bfc13e 100644 --- a/internal/backend/fs.go +++ b/internal/backend/fs.go @@ -437,7 +437,7 @@ func concatObjectReaders(objects []StreamingObject) io.ReadSeekCloser { return concatenatedContent{io.MultiReader(readers...)} } -func (s *storageFS) ComposeObject(bucketName string, objectNames []string, destinationName string, metadata map[string]string, contentType string) (StreamingObject, error) { +func (s *storageFS) ComposeObject(bucketName string, objectNames []string, destinationName string, metadata map[string]string, contentType string, contentDisposition string, contentLanguage string) (StreamingObject, error) { var sourceObjects []StreamingObject for _, n := range objectNames { obj, err := s.GetObject(bucketName, n) @@ -454,6 +454,8 @@ func (s *storageFS) ComposeObject(bucketName string, objectNames []string, desti BucketName: bucketName, Name: destinationName, ContentType: contentType, + ContentDisposition: contentDisposition, + ContentLanguage: contentLanguage, Created: now, Updated: now, }, diff --git a/internal/backend/memory.go b/internal/backend/memory.go index f202ff3694..133265f597 100644 --- a/internal/backend/memory.go +++ b/internal/backend/memory.go @@ -344,7 +344,7 @@ func (s *storageMemory) UpdateObject(bucketName, objectName string, attrsToUpdat return obj, nil } -func (s *storageMemory) ComposeObject(bucketName string, objectNames []string, destinationName string, metadata map[string]string, contentType string) (StreamingObject, error) { +func (s *storageMemory) ComposeObject(bucketName string, objectNames []string, destinationName string, metadata map[string]string, contentType string, contentDisposition string, contentLanguage string) (StreamingObject, error) { var data []byte for _, n := range objectNames { obj, err := s.GetObject(bucketName, n) @@ -367,6 +367,8 @@ func (s *storageMemory) ComposeObject(bucketName string, objectNames []string, d BucketName: bucketName, Name: destinationName, ContentType: contentType, + ContentDisposition: contentDisposition, + ContentLanguage: contentLanguage, Created: now, Updated: now, }, diff --git a/internal/backend/storage.go b/internal/backend/storage.go index fd382ae983..c428fcc8d2 100644 --- a/internal/backend/storage.go +++ b/internal/backend/storage.go @@ -30,7 +30,7 @@ type Storage interface { DeleteObject(bucketName, objectName string) error PatchObject(bucketName, objectName string, attrsToUpdate ObjectAttrs) (StreamingObject, error) UpdateObject(bucketName, objectName string, attrsToUpdate ObjectAttrs) (StreamingObject, error) - ComposeObject(bucketName string, objectNames []string, destinationName string, metadata map[string]string, contentType string) (StreamingObject, error) + ComposeObject(bucketName string, objectNames []string, destinationName string, metadata map[string]string, contentType string, contentDisposition string, contentLanguage string) (StreamingObject, error) DeleteAllFiles() error } diff --git a/internal/grpc/server.go b/internal/grpc/server.go index 928344538d..42df543470 100644 --- a/internal/grpc/server.go +++ b/internal/grpc/server.go @@ -144,13 +144,13 @@ func (g *Server) PatchObject(ctx context.Context, req *pb.PatchObjectRequest) (* return makeObject(obj), err } -// ComposeObject(bucketName string, objectNames []string, destinationName string, metadata map[string]string, contentType string) +// ComposeObject(bucketName string, objectNames []string, destinationName string, metadata map[string]string, contentType string, contentDisposition string, contentLanguage string) func (g *Server) ComposeObject(ctx context.Context, req *pb.ComposeObjectRequest) (*pb.Object, error) { sourceObjNames := make([]string, 2) for i := 0; i < len(req.SourceObjects); i++ { sourceObjNames[i] = req.SourceObjects[i].Name } - obj, err := g.backend.ComposeObject(req.DestinationBucket, sourceObjNames, req.DestinationObject, map[string]string{}, "") + obj, err := g.backend.ComposeObject(req.DestinationBucket, sourceObjNames, req.DestinationObject, map[string]string{}, "", "", "") return makeObject(obj), err }