From 86f0e3edda77ce24671bf93bc22631496a5840b8 Mon Sep 17 00:00:00 2001 From: Iwan BK Date: Thu, 16 Jan 2025 21:12:13 +0700 Subject: [PATCH] migrate copy_object. It doesn't have integration test because the s3 client library we use in the test doesn't support copy_object features that we support. --- src/s3fs.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/src/s3fs.rs b/src/s3fs.rs index 41b1fd3..d459d6a 100644 --- a/src/s3fs.rs +++ b/src/s3fs.rs @@ -17,14 +17,14 @@ use s3_server::dto::ByteStream; use s3s::dto::StreamingBlob; use s3s::dto::Timestamp; use s3s::dto::{ - Bucket, CompleteMultipartUploadInput, CompleteMultipartUploadOutput, CreateBucketInput, - CreateBucketOutput, CreateMultipartUploadInput, CreateMultipartUploadOutput, DeleteBucketInput, - DeleteBucketOutput, DeleteObjectInput, DeleteObjectOutput, DeleteObjectsInput, - DeleteObjectsOutput, DeletedObject, GetBucketLocationInput, GetBucketLocationOutput, - GetObjectInput, GetObjectOutput, HeadBucketInput, HeadBucketOutput, HeadObjectInput, - HeadObjectOutput, ListBucketsInput, ListBucketsOutput, ListObjectsInput, ListObjectsOutput, - ListObjectsV2Input, ListObjectsV2Output, PutObjectInput, PutObjectOutput, UploadPartInput, - UploadPartOutput, + Bucket, CompleteMultipartUploadInput, CompleteMultipartUploadOutput, CopyObjectInput, + CopyObjectOutput, CopyObjectResult, CopySource, CreateBucketInput, CreateBucketOutput, + CreateMultipartUploadInput, CreateMultipartUploadOutput, DeleteBucketInput, DeleteBucketOutput, + DeleteObjectInput, DeleteObjectOutput, DeleteObjectsInput, DeleteObjectsOutput, DeletedObject, + GetBucketLocationInput, GetBucketLocationOutput, GetObjectInput, GetObjectOutput, + HeadBucketInput, HeadBucketOutput, HeadObjectInput, HeadObjectOutput, ListBucketsInput, + ListBucketsOutput, ListObjectsInput, ListObjectsOutput, ListObjectsV2Input, + ListObjectsV2Output, PutObjectInput, PutObjectOutput, UploadPartInput, UploadPartOutput, }; use s3s::s3_error; use s3s::S3Result; @@ -172,6 +172,50 @@ impl S3 for S3FS { Ok(S3Response::new(output)) } + async fn copy_object( + &self, + req: S3Request, + ) -> S3Result> { + let input = req.input; + let (bucket, key) = match input.copy_source { + CopySource::AccessPoint { .. } => return Err(s3_error!(NotImplemented)), + CopySource::Bucket { + ref bucket, + ref key, + .. + } => (bucket, key), + }; + + if !try_!(self.casfs.bucket_exists(bucket)) { + return Err(s3_error!(NoSuchBucket, "Target bucket does not exist").into()); + } + + let source_bk = try_!(self.casfs.bucket(&input.bucket)); + let mut obj_meta = match try_!(source_bk.get(&input.key)) { + // unwrap here is safe as it means the DB is corrupted + Some(enc_meta) => Object::try_from(&*enc_meta).unwrap(), + None => return Err(s3_error!(NoSuchKey, "Source key does not exist").into()), + }; + + obj_meta.touch(); + + // TODO: check duplicate? + let dst_bk = try_!(self.casfs.bucket(bucket)); + try_!(dst_bk.insert(key.as_bytes(), Vec::::from(&obj_meta))); + + let copy_object_result = CopyObjectResult { + e_tag: Some(obj_meta.format_e_tag()), + last_modified: Some(obj_meta.last_modified().into()), + ..Default::default() + }; + + let output = CopyObjectOutput { + copy_object_result: Some(copy_object_result), + ..Default::default() + }; + Ok(S3Response::new(output)) + } + async fn create_bucket( &self, req: S3Request,