This is an automated email from the ASF dual-hosted git repository. suyanhanx pushed a commit to branch webdav-copy in repository https://gitbox.apache.org/repos/asf/incubator-opendal.git
commit 72dd6a31eefcb165e3653256fc7a83fa8953564f Author: suyanhanx <[email protected]> AuthorDate: Fri Apr 7 15:36:42 2023 +0800 feat(webdav): support copy Signed-off-by: suyanhanx <[email protected]> --- core/src/services/webdav/backend.rs | 42 ++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/core/src/services/webdav/backend.rs b/core/src/services/webdav/backend.rs index 5b1180c5..ca824b6e 100644 --- a/core/src/services/webdav/backend.rs +++ b/core/src/services/webdav/backend.rs @@ -44,6 +44,7 @@ use crate::*; /// /// - [x] read /// - [x] write +/// - [x] copy /// - [x] list /// - [ ] ~~scan~~ /// - [ ] ~~presign~~ @@ -265,7 +266,10 @@ impl Accessor for WebdavBackend { ma.set_scheme(Scheme::Webdav) .set_root(&self.root) .set_capabilities( - AccessorCapability::Read | AccessorCapability::Write | AccessorCapability::List, + AccessorCapability::Read + | AccessorCapability::Write + | AccessorCapability::Copy + | AccessorCapability::List, ) .set_hints(AccessorHint::ReadStreamable); @@ -318,6 +322,17 @@ impl Accessor for WebdavBackend { Ok((RpWrite::default(), WebdavWriter::new(self.clone(), args, p))) } + async fn copy(&self, from: &str, to: &str, _args: OpCopy) -> Result<RpCopy> { + let resp = self.webdav_copy(from, to).await?; + + let status = resp.status(); + + match status { + StatusCode::CREATED | StatusCode::NO_CONTENT => Ok(RpCopy::default()), + _ => Err(parse_error(resp).await?), + } + } + async fn stat(&self, path: &str, _: OpStat) -> Result<RpStat> { // Stat root always returns a DIR. if path == "/" { @@ -549,6 +564,31 @@ impl WebdavBackend { self.client.send_async(req).await } + async fn webdav_copy(&self, from: &str, to: &str) -> Result<Response<IncomingAsyncBody>> { + let source = build_abs_path(&self.root, from); + let target = build_abs_path(&self.root, to); + + let source = format!("{}/{}", self.endpoint, percent_encode_path(&source)); + let target = format!("{}/{}", self.endpoint, percent_encode_path(&target)); + + let mut req = Request::builder().method("COPY").uri(&source); + + if let Some(auth) = &self.authorization { + req = req.header(header::AUTHORIZATION, auth); + } + + req = req.header("Destination", target); + + // We always specific "T" for keeping to overwrite the destination. + req = req.header("Overwrite", "T"); + + let req = req + .body(AsyncBody::Empty) + .map_err(new_request_build_error)?; + + self.client.send_async(req).await + } + async fn create_internal(&self, abs_path: &str) -> Result<RpCreate> { let resp = if abs_path.ends_with('/') { self.webdav_mkcol(abs_path, None, None, AsyncBody::Empty)
