diff --git a/core/src/services/oss/backend.rs b/core/src/services/oss/backend.rs index a1bfeacfe5c..1e141519829 100644 --- a/core/src/services/oss/backend.rs +++ b/core/src/services/oss/backend.rs @@ -53,6 +53,7 @@ use crate::*; /// /// - [x] read /// - [x] write +/// - [x] copy /// - [x] list /// - [x] scan /// - [ ] presign @@ -417,7 +418,7 @@ impl Accessor for OssBackend { .set_root(&self.root) .set_name(&self.bucket) .set_max_batch_operations(1000) - .set_capabilities(Read | Write | List | Scan | Presign | Batch) + .set_capabilities(Read | Write | Copy | List | Scan | Presign | Batch) .set_hints(ReadStreamable); am @@ -475,6 +476,19 @@ impl Accessor for OssBackend { )) } + async fn copy(&self, from: &str, to: &str, _args: OpCopy) -> Result { + let resp = self.oss_copy_object(from, to).await?; + let status = resp.status(); + + match status { + StatusCode::OK => { + resp.into_body().consume().await?; + Ok(RpCopy::default()) + } + _ => Err(parse_error(resp).await?), + } + } + async fn stat(&self, path: &str, _: OpStat) -> Result { if path == "/" { let m = Metadata::new(EntryMode::DIR); @@ -756,6 +770,26 @@ impl OssBackend { self.client.send_async(req).await } + async fn oss_copy_object(&self, from: &str, to: &str) -> Result> { + let source = build_abs_path(&self.root, from); + let target = build_abs_path(&self.root, to); + + let url = format!( + "{}/{}", + self.get_endpoint(false), + percent_encode_path(&target) + ); + let source = format!("/{}/{}", self.bucket, percent_encode_path(&source)); + + let mut req = Request::put(&url) + .header("x-oss-copy-source", source) + .body(AsyncBody::Empty) + .map_err(new_request_build_error)?; + + self.signer.sign(&mut req).map_err(new_request_sign_error)?; + self.client.send_async(req).await + } + pub(super) async fn oss_list_object( &self, path: &str,