From 4b33fcdecdf4d3752bbe42f8155b5b66f2de144b Mon Sep 17 00:00:00 2001 From: Flash <71162630+Young-Flash@users.noreply.github.com> Date: Wed, 9 Aug 2023 22:34:20 +0800 Subject: [PATCH] feat: Add create_dir, remove, copy and rename API for oay-webdav (#2832) * impl some missing api for oay-webdav * use `map_err` to omit `match` --- bin/oay/src/services/webdav/webdav_file.rs | 2 +- bin/oay/src/services/webdav/webdavfs.rs | 87 +++++++++++++++++++++- 2 files changed, 85 insertions(+), 4 deletions(-) diff --git a/bin/oay/src/services/webdav/webdav_file.rs b/bin/oay/src/services/webdav/webdav_file.rs index 5a10813ea0ce..73e1892be979 100644 --- a/bin/oay/src/services/webdav/webdav_file.rs +++ b/bin/oay/src/services/webdav/webdav_file.rs @@ -83,7 +83,7 @@ impl DavFile for WebdavFile { } } -fn convert_error(opendal_error: opendal::Error) -> dav_server::fs::FsError { +pub fn convert_error(opendal_error: opendal::Error) -> dav_server::fs::FsError { match opendal_error.kind() { opendal::ErrorKind::AlreadyExists | opendal::ErrorKind::IsSameFile => { dav_server::fs::FsError::Exists diff --git a/bin/oay/src/services/webdav/webdavfs.rs b/bin/oay/src/services/webdav/webdavfs.rs index 3eda5c539924..0a974dfd91d2 100644 --- a/bin/oay/src/services/webdav/webdavfs.rs +++ b/bin/oay/src/services/webdav/webdavfs.rs @@ -15,9 +15,11 @@ // specific language governing permissions and limitations // under the License. +use std::path::Path; use std::pin::Pin; use std::task::Poll::{Pending, Ready}; +use dav_server::davpath::DavPath; use dav_server::fs::DavDirEntry; use dav_server::fs::DavFile; use dav_server::fs::DavFileSystem; @@ -30,7 +32,7 @@ use opendal::Operator; use crate::services::webdav::webdav_dir_entry::WebDAVDirEntry; -use super::webdav_file::WebdavFile; +use super::webdav_file::{convert_error, WebdavFile}; use super::webdav_metadata::WebdavMetaData; #[derive(Clone)] @@ -73,8 +75,87 @@ impl DavFileSystem for WebdavFs { path: &'a dav_server::davpath::DavPath, ) -> dav_server::fs::FsFuture> { async move { - let opendal_metadata = self.op.stat(path.as_url_string().as_str()).await.unwrap(); - Ok(Box::new(WebdavMetaData::new(opendal_metadata)) as Box) + let opendal_metadata = self.op.stat(path.as_url_string().as_str()).await; + match opendal_metadata { + Ok(metadata) => { + let webdav_metadata = WebdavMetaData::new(metadata); + Ok(Box::new(webdav_metadata) as Box) + } + Err(e) => Err(convert_error(e)), + } + } + .boxed() + } + + fn create_dir<'a>(&'a self, path: &'a DavPath) -> dav_server::fs::FsFuture<()> { + async move { + let path = path.as_url_string(); + + // check if the parent path is exist. + // During MKCOL processing, a server MUST make the Request-URI a member of its parent collection, unless the Request-URI is "/". If no such ancestor exists, the method MUST fail. + // refer to https://datatracker.ietf.org/doc/html/rfc2518#section-8.3.1 + let parent = Path::new(&path).parent().unwrap(); + match self.op.is_exist(parent.to_str().unwrap()).await { + Ok(exist) => { + if !exist && parent != Path::new("/") { + return Err(dav_server::fs::FsError::NotFound); + } + } + Err(e) => { + return Err(convert_error(e)); + } + } + + let path = path.as_str(); + // check if the given path is exist (MKCOL on existing collection should fail (RFC2518:8.3.1)) + let exist = self.op.is_exist(path).await; + match exist { + Ok(exist) => match exist { + true => Err(dav_server::fs::FsError::Exists), + false => { + let res = self.op.create_dir(path).await; + match res { + Ok(_) => Ok(()), + Err(e) => Err(convert_error(e)), + } + } + }, + Err(e) => Err(convert_error(e)), + } + } + .boxed() + } + + fn remove_file<'a>(&'a self, path: &'a DavPath) -> dav_server::fs::FsFuture<()> { + async move { + self.op + .delete(path.as_url_string().as_str()) + .await + .map_err(convert_error) + } + .boxed() + } + + fn remove_dir<'a>(&'a self, path: &'a DavPath) -> dav_server::fs::FsFuture<()> { + self.remove_file(path) + } + + fn copy<'a>(&'a self, from: &'a DavPath, to: &'a DavPath) -> dav_server::fs::FsFuture<()> { + async move { + self.op + .copy(&from.as_url_string(), &to.as_url_string()) + .await + .map_err(convert_error) + } + .boxed() + } + + fn rename<'a>(&'a self, from: &'a DavPath, to: &'a DavPath) -> dav_server::fs::FsFuture<()> { + async move { + self.op + .rename(from.as_url_string().as_str(), to.as_url_string().as_str()) + .await + .map_err(convert_error) } .boxed() }