feat: Implements object meta properties for CopyObject in azure and posix backends.

Fixes #998
Closes #1125
Closes #1126
Closes #1127

Implements objects meta properties(Content-Disposition, Content-Language, Content-Encoding, Cache-Control, Expires) and tagging besed on the directives(metadata, tagging) in CopyObject in posix and azure backends. The properties/tagging should be coppied from the source object if "COPY" directive is provided and it should be replaced otherwise.

Changes the object copy principle in azure: instead of using the `CopyFromURL` method from azure sdk, it first loads the object then creates one, to be able to compare and store the meta properties.
This commit is contained in:
niksis02
2025-03-17 19:20:11 +04:00
committed by Ben McClelland
parent 38768a92b8
commit cfb2d6d87d
13 changed files with 819 additions and 61 deletions

View File

@@ -988,7 +988,7 @@ func (s *S3Proxy) GetObjectAttributes(ctx context.Context, input *s3.GetObjectAt
}, handleError(err)
}
func (s *S3Proxy) CopyObject(ctx context.Context, input *s3.CopyObjectInput) (*s3.CopyObjectOutput, error) {
func (s *S3Proxy) CopyObject(ctx context.Context, input s3response.CopyObjectInput) (*s3.CopyObjectOutput, error) {
if input.CacheControl != nil && *input.CacheControl == "" {
input.CacheControl = nil
}
@@ -1031,7 +1031,7 @@ func (s *S3Proxy) CopyObject(ctx context.Context, input *s3.CopyObjectInput) (*s
if input.ExpectedSourceBucketOwner != nil && *input.ExpectedSourceBucketOwner == "" {
input.ExpectedSourceBucketOwner = nil
}
if input.Expires != nil && *input.Expires == defTime {
if input.Expires != nil && *input.Expires == "" {
input.Expires = nil
}
if input.GrantFullControl != nil && *input.GrantFullControl == "" {
@@ -1071,7 +1071,58 @@ func (s *S3Proxy) CopyObject(ctx context.Context, input *s3.CopyObjectInput) (*s
input.WebsiteRedirectLocation = nil
}
out, err := s.client.CopyObject(ctx, input)
var expires *time.Time
if input.Expires != nil {
exp, err := time.Parse(time.RFC1123, *input.Expires)
if err == nil {
expires = &exp
}
}
out, err := s.client.CopyObject(ctx,
&s3.CopyObjectInput{
Metadata: input.Metadata,
Bucket: input.Bucket,
CopySource: input.CopySource,
Key: input.Key,
CacheControl: input.CacheControl,
ContentDisposition: input.ContentDisposition,
ContentEncoding: input.ContentEncoding,
ContentLanguage: input.ContentLanguage,
ContentType: input.ContentType,
CopySourceIfMatch: input.CopySourceIfMatch,
CopySourceIfNoneMatch: input.CopySourceIfNoneMatch,
CopySourceSSECustomerAlgorithm: input.CopySourceSSECustomerAlgorithm,
CopySourceSSECustomerKey: input.CopySourceSSECustomerKey,
CopySourceSSECustomerKeyMD5: input.CopySourceSSECustomerKeyMD5,
ExpectedBucketOwner: input.ExpectedBucketOwner,
ExpectedSourceBucketOwner: input.ExpectedSourceBucketOwner,
Expires: expires,
GrantFullControl: input.GrantFullControl,
GrantRead: input.GrantRead,
GrantReadACP: input.GrantReadACP,
GrantWriteACP: input.GrantWriteACP,
SSECustomerAlgorithm: input.SSECustomerAlgorithm,
SSECustomerKey: input.SSECustomerKey,
SSECustomerKeyMD5: input.SSECustomerKeyMD5,
SSEKMSEncryptionContext: input.SSEKMSEncryptionContext,
SSEKMSKeyId: input.SSEKMSKeyId,
Tagging: input.Tagging,
WebsiteRedirectLocation: input.WebsiteRedirectLocation,
CopySourceIfModifiedSince: input.CopySourceIfModifiedSince,
CopySourceIfUnmodifiedSince: input.CopySourceIfUnmodifiedSince,
ObjectLockRetainUntilDate: input.ObjectLockRetainUntilDate,
BucketKeyEnabled: input.BucketKeyEnabled,
ACL: input.ACL,
ChecksumAlgorithm: input.ChecksumAlgorithm,
MetadataDirective: input.MetadataDirective,
ObjectLockLegalHoldStatus: input.ObjectLockLegalHoldStatus,
ObjectLockMode: input.ObjectLockMode,
RequestPayer: input.RequestPayer,
ServerSideEncryption: input.ServerSideEncryption,
StorageClass: input.StorageClass,
TaggingDirective: input.TaggingDirective,
})
return out, handleError(err)
}