Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add disposition and language to ComposeObject #1865

Merged
merged 1 commit into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion fakestorage/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
80 changes: 52 additions & 28 deletions fakestorage/object_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2123,10 +2123,12 @@ func TestParseRangeRequest(t *testing.T) {

func TestServiceClientComposeObject(t *testing.T) {
const (
source1Content = "some content"
source2Content = "other content"
source3Content = "third test"
contentType = "text/plain; charset=utf-8"
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))
hash := checksum.MD5Hash([]byte(source1Content))
Expand All @@ -2135,45 +2137,53 @@ func TestServiceClientComposeObject(t *testing.T) {
objs := []Object{
{
ObjectAttrs: ObjectAttrs{
BucketName: "first-bucket",
Name: "files/source1.txt",
ContentType: contentType,
Crc32c: checksum.EncodedChecksum(uint32ToBytes(u32Checksum)),
Md5Hash: checksum.EncodedHash(hash),
Metadata: map[string]string{"foo": "bar"},
BucketName: "first-bucket",
Name: "files/source1.txt",
ContentDisposition: contentDisposition,
ContentLanguage: contentLanguage,
ContentType: contentType,
Crc32c: checksum.EncodedChecksum(uint32ToBytes(u32Checksum)),
Md5Hash: checksum.EncodedHash(hash),
Metadata: map[string]string{"foo": "bar"},
},
Content: []byte(source1Content),
},
{
ObjectAttrs: ObjectAttrs{
BucketName: "first-bucket",
Name: "files/source2.txt",
ContentType: contentType,
Crc32c: checksum.EncodedChecksum(uint32ToBytes(u32Checksum)),
Md5Hash: checksum.EncodedHash(hash),
Metadata: map[string]string{"foo": "bar"},
BucketName: "first-bucket",
Name: "files/source2.txt",
ContentDisposition: contentDisposition,
ContentLanguage: contentLanguage,
ContentType: contentType,
Crc32c: checksum.EncodedChecksum(uint32ToBytes(u32Checksum)),
Md5Hash: checksum.EncodedHash(hash),
Metadata: map[string]string{"foo": "bar"},
},
Content: []byte(source2Content),
},
{
ObjectAttrs: ObjectAttrs{
BucketName: "first-bucket",
Name: "files/source3.txt",
ContentType: contentType,
Crc32c: checksum.EncodedChecksum(uint32ToBytes(u32Checksum)),
Md5Hash: checksum.EncodedHash(hash),
Metadata: map[string]string{"foo": "bar"},
BucketName: "first-bucket",
Name: "files/source3.txt",
ContentDisposition: contentDisposition,
ContentLanguage: contentLanguage,
ContentType: contentType,
Crc32c: checksum.EncodedChecksum(uint32ToBytes(u32Checksum)),
Md5Hash: checksum.EncodedHash(hash),
Metadata: map[string]string{"foo": "bar"},
},
Content: []byte(source3Content),
},
{
ObjectAttrs: ObjectAttrs{
BucketName: "first-bucket",
Name: "files/destination.txt",
ContentType: contentType,
Crc32c: checksum.EncodedChecksum(uint32ToBytes(u32Checksum)),
Md5Hash: checksum.EncodedHash(hash),
Metadata: map[string]string{"foo": "bar"},
BucketName: "first-bucket",
Name: "files/destination.txt",
ContentDisposition: contentDisposition,
ContentLanguage: contentLanguage,
ContentType: contentType,
Crc32c: checksum.EncodedChecksum(uint32ToBytes(u32Checksum)),
Md5Hash: checksum.EncodedHash(hash),
Metadata: map[string]string{"foo": "bar"},
},
Content: []byte("test"),
},
Expand Down Expand Up @@ -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())
Expand All @@ -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)
}
Expand All @@ -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)
}
Expand Down
14 changes: 8 additions & 6 deletions internal/backend/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -451,11 +451,13 @@ func (s *storageFS) ComposeObject(bucketName string, objectNames []string, desti
now := time.Now().Format(timestampFormat)
dest := StreamingObject{
ObjectAttrs: ObjectAttrs{
BucketName: bucketName,
Name: destinationName,
ContentType: contentType,
Created: now,
Updated: now,
BucketName: bucketName,
Name: destinationName,
ContentType: contentType,
ContentDisposition: contentDisposition,
ContentLanguage: contentLanguage,
Created: now,
Updated: now,
},
}

Expand Down
14 changes: 8 additions & 6 deletions internal/backend/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -364,11 +364,13 @@ func (s *storageMemory) ComposeObject(bucketName string, objectNames []string, d
now := time.Now().Format(timestampFormat)
dest = Object{
ObjectAttrs: ObjectAttrs{
BucketName: bucketName,
Name: destinationName,
ContentType: contentType,
Created: now,
Updated: now,
BucketName: bucketName,
Name: destinationName,
ContentType: contentType,
ContentDisposition: contentDisposition,
ContentLanguage: contentLanguage,
Created: now,
Updated: now,
},
}
} else {
Expand Down
2 changes: 1 addition & 1 deletion internal/backend/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
4 changes: 2 additions & 2 deletions internal/grpc/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
Loading