This is an automated email from the ASF dual-hosted git repository.
xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-opendal.git
The following commit(s) were added to refs/heads/main by this push:
new be3cfa240 refactor(oay): import dav-server-opendalfs (#3285)
be3cfa240 is described below
commit be3cfa240db6feb93c68b4cbe2b0f545c48e3396
Author: Flash <[email protected]>
AuthorDate: Sun Oct 15 16:25:07 2023 +0800
refactor(oay): import dav-server-opendalfs (#3285)
---
Cargo.lock | 1 +
bin/oay/Cargo.toml | 3 +-
bin/oay/src/services/webdav/mod.rs | 6 +-
bin/oay/src/services/webdav/service.rs | 8 +-
bin/oay/src/services/webdav/webdav_dir_entry.rs | 54 ------
bin/oay/src/services/webdav/webdav_file.rs | 94 ----------
bin/oay/src/services/webdav/webdav_metadata.rs | 62 -------
bin/oay/src/services/webdav/webdavfs.rs | 220 ------------------------
8 files changed, 8 insertions(+), 440 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
index 58cfcd679..c0f7a71b2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3851,6 +3851,7 @@ dependencies = [
"chrono",
"clap 4.3.10",
"dav-server",
+ "dav-server-opendalfs",
"dirs 5.0.1",
"futures",
"futures-util",
diff --git a/bin/oay/Cargo.toml b/bin/oay/Cargo.toml
index 4e3f57d83..d8df51753 100644
--- a/bin/oay/Cargo.toml
+++ b/bin/oay/Cargo.toml
@@ -33,7 +33,7 @@ version.workspace = true
default = ["frontends-webdav", "frontends-s3"]
frontends-s3 = []
-frontends-webdav = ["dep:dav-server", "dep:bytes", "dep:futures-util"]
+frontends-webdav = ["dep:dav-server", "dep:dav-server-opendalfs", "dep:bytes",
"dep:futures-util"]
[dependencies]
anyhow = "1"
@@ -42,6 +42,7 @@ bytes = { version = "1.4.0", optional = true }
chrono = "0.4.28"
clap = { version = "4", features = ["cargo", "string"] }
dav-server = { version = "0.5.5", optional = true }
+dav-server-opendalfs = { path = "../../integrations/dav-server", optional =
true }
dirs = "5.0.0"
futures = "0.3"
futures-util = { version = "0.3.16", optional = true }
diff --git a/bin/oay/src/services/webdav/mod.rs
b/bin/oay/src/services/webdav/mod.rs
index e432889a8..bcf580055 100644
--- a/bin/oay/src/services/webdav/mod.rs
+++ b/bin/oay/src/services/webdav/mod.rs
@@ -16,8 +16,4 @@
// under the License.
mod service;
-mod webdav_dir_entry;
-mod webdav_file;
-mod webdav_metadata;
-pub mod webdavfs;
-pub use service::*;
+pub use service::WebdavService;
diff --git a/bin/oay/src/services/webdav/service.rs
b/bin/oay/src/services/webdav/service.rs
index 6a1bcf552..71bc31499 100644
--- a/bin/oay/src/services/webdav/service.rs
+++ b/bin/oay/src/services/webdav/service.rs
@@ -25,19 +25,19 @@ use axum::Router;
use dav_server::DavHandler;
use opendal::Operator;
-use super::webdavfs::WebdavFs;
use crate::Config;
+use dav_server_opendalfs::OpendalFs;
pub struct WebdavService {
cfg: Arc<Config>,
- webdavfs: Box<WebdavFs>,
+ opendalfs: Box<OpendalFs>,
}
impl WebdavService {
pub fn new(cfg: Arc<Config>, op: Operator) -> Self {
Self {
cfg,
- webdavfs: WebdavFs::new(op),
+ opendalfs: OpendalFs::new(op),
}
}
@@ -45,7 +45,7 @@ impl WebdavService {
let webdav_cfg = &self.cfg.frontends.webdav;
let webdav_handler = DavHandler::builder()
- .filesystem(self.webdavfs.clone())
+ .filesystem(self.opendalfs.clone())
.build_handler();
let webdav_service = tower::service_fn(move |req: Request<Body>| {
diff --git a/bin/oay/src/services/webdav/webdav_dir_entry.rs
b/bin/oay/src/services/webdav/webdav_dir_entry.rs
deleted file mode 100644
index c3836db3e..000000000
--- a/bin/oay/src/services/webdav/webdav_dir_entry.rs
+++ /dev/null
@@ -1,54 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use dav_server::fs::DavDirEntry;
-use futures::FutureExt;
-use opendal::Entry;
-use opendal::Operator;
-
-use super::webdav_file::convert_error;
-use super::webdav_metadata::WebdavMetaData;
-
-pub struct WebDAVDirEntry {
- dir_entry: Entry,
- op: Operator,
-}
-
-impl DavDirEntry for WebDAVDirEntry {
- fn name(&self) -> Vec<u8> {
- self.dir_entry.name().as_bytes().to_vec()
- }
-
- fn metadata(&self) -> dav_server::fs::FsFuture<Box<dyn
dav_server::fs::DavMetaData>> {
- async move {
- self.op
- .stat(self.dir_entry.path())
- .await
- .map(|metadata| {
- Box::new(WebdavMetaData::new(metadata)) as Box<dyn
dav_server::fs::DavMetaData>
- })
- .map_err(convert_error)
- }
- .boxed()
- }
-}
-
-impl WebDAVDirEntry {
- pub fn new(dir_entry: Entry, op: Operator) -> Self {
- WebDAVDirEntry { dir_entry, op }
- }
-}
diff --git a/bin/oay/src/services/webdav/webdav_file.rs
b/bin/oay/src/services/webdav/webdav_file.rs
deleted file mode 100644
index 53e99c07f..000000000
--- a/bin/oay/src/services/webdav/webdav_file.rs
+++ /dev/null
@@ -1,94 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use std::io::SeekFrom;
-
-use bytes::Bytes;
-use dav_server::davpath::DavPath;
-use dav_server::fs::DavFile;
-use dav_server::fs::DavMetaData;
-use dav_server::fs::FsFuture;
-use dav_server::fs::OpenOptions;
-use futures::FutureExt;
-use opendal::Operator;
-
-use super::webdav_metadata::WebdavMetaData;
-
-#[derive(Debug)]
-pub struct WebdavFile {
- pub op: Operator,
- pub path: DavPath,
- pub options: OpenOptions,
-}
-
-impl DavFile for WebdavFile {
- fn read_bytes(&mut self, count: usize) -> FsFuture<Bytes> {
- async move {
- let file_path = self.path.as_url_string();
- self.op
- .read_with(&file_path)
- .range(0..count as u64)
- .await
- .map(Bytes::from)
- .map_err(convert_error)
- }
- .boxed()
- }
-
- fn metadata(&mut self) -> FsFuture<Box<dyn DavMetaData>> {
- async move {
- self.op
- .stat(self.path.as_url_string().as_str())
- .await
- .map(|opendal_metadata| {
- Box::new(WebdavMetaData::new(opendal_metadata)) as Box<dyn
DavMetaData>
- })
- .map_err(convert_error)
- }
- .boxed()
- }
-
- fn write_buf(&mut self, buf: Box<dyn bytes::Buf + Send>) -> FsFuture<()> {
- self.write_bytes(Bytes::copy_from_slice(buf.chunk()))
- }
-
- fn write_bytes(&mut self, buf: Bytes) -> FsFuture<()> {
- async move {
- let file_path = self.path.as_url_string();
- self.op.write(&file_path, buf).await.map_err(convert_error)
- }
- .boxed()
- }
-
- fn seek(&mut self, _pos: SeekFrom) -> FsFuture<u64> {
-
futures_util::future::err(dav_server::fs::FsError::NotImplemented).boxed()
- }
-
- fn flush(&mut self) -> FsFuture<()> {
- futures_util::future::ok(()).boxed()
- }
-}
-
-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
- }
- opendal::ErrorKind::NotFound => dav_server::fs::FsError::NotFound,
- _ => dav_server::fs::FsError::GeneralFailure,
- }
-}
diff --git a/bin/oay/src/services/webdav/webdav_metadata.rs
b/bin/oay/src/services/webdav/webdav_metadata.rs
deleted file mode 100644
index 03295125d..000000000
--- a/bin/oay/src/services/webdav/webdav_metadata.rs
+++ /dev/null
@@ -1,62 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use dav_server::fs::DavMetaData;
-use dav_server::fs::FsError;
-use opendal::Metadata;
-
-#[derive(Debug, Clone)]
-pub struct WebdavMetaData {
- metadata: Metadata,
-}
-
-impl WebdavMetaData {
- pub fn new(metadata: Metadata) -> Self {
- WebdavMetaData { metadata }
- }
-}
-
-impl DavMetaData for WebdavMetaData {
- fn len(&self) -> u64 {
- self.metadata.content_length()
- }
-
- fn modified(&self) -> dav_server::fs::FsResult<std::time::SystemTime> {
- match self.metadata.last_modified() {
- Some(t) => Ok(t.into()),
- None => Err(FsError::GeneralFailure),
- }
- }
-
- fn is_dir(&self) -> bool {
- self.metadata.is_dir()
- }
-
- fn is_file(&self) -> bool {
- self.metadata.is_file()
- }
-
- fn etag(&self) -> Option<String> {
- self.metadata.etag().map(|s| s.to_string())
- }
-
- fn status_changed(&self) ->
dav_server::fs::FsResult<std::time::SystemTime> {
- self.metadata
- .last_modified()
- .map_or(Err(FsError::GeneralFailure), |t| Ok(t.into()))
- }
-}
diff --git a/bin/oay/src/services/webdav/webdavfs.rs
b/bin/oay/src/services/webdav/webdavfs.rs
deleted file mode 100644
index b4167dbaa..000000000
--- a/bin/oay/src/services/webdav/webdavfs.rs
+++ /dev/null
@@ -1,220 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use std::path::Path;
-use std::pin::Pin;
-use std::task::Poll::Pending;
-use std::task::Poll::Ready;
-
-use dav_server::davpath::DavPath;
-use dav_server::fs::DavDirEntry;
-use dav_server::fs::DavFile;
-use dav_server::fs::DavFileSystem;
-use dav_server::fs::DavMetaData;
-use dav_server::fs::FsError;
-use futures::FutureExt;
-use futures_util::Stream;
-use futures_util::StreamExt;
-use opendal::Lister;
-use opendal::Operator;
-
-use super::webdav_file::convert_error;
-use super::webdav_file::WebdavFile;
-use super::webdav_metadata::WebdavMetaData;
-use crate::services::webdav::webdav_dir_entry::WebDAVDirEntry;
-
-#[derive(Clone)]
-pub struct WebdavFs {
- pub op: Operator,
-}
-
-impl DavFileSystem for WebdavFs {
- fn open<'a>(
- &'a self,
- path: &'a dav_server::davpath::DavPath,
- options: dav_server::fs::OpenOptions,
- ) -> dav_server::fs::FsFuture<Box<dyn dav_server::fs::DavFile>> {
- async move {
- let file = WebdavFile {
- op: self.op.clone(),
- path: path.clone(),
- options,
- };
- Ok(Box::new(file) as Box<dyn DavFile>)
- }
- .boxed()
- }
-
- fn read_dir<'a>(
- &'a self,
- path: &'a dav_server::davpath::DavPath,
- _meta: dav_server::fs::ReadDirMeta,
- ) -> dav_server::fs::FsFuture<dav_server::fs::FsStream<Box<dyn
dav_server::fs::DavDirEntry>>>
- {
- async move {
- self.op
- .lister(path.as_url_string().as_str())
- .await
- .map(|lister| DavStream::new(self.op.clone(), lister).boxed())
- .map_err(convert_error)
- }
- .boxed()
- }
-
- fn metadata<'a>(
- &'a self,
- path: &'a dav_server::davpath::DavPath,
- ) -> dav_server::fs::FsFuture<Box<dyn dav_server::fs::DavMetaData>> {
- async move {
- 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<dyn DavMetaData>)
- }
- 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 {
- let from_path = from
- .as_rel_ospath()
- .to_str()
- .ok_or(FsError::GeneralFailure)?;
- let to_path =
to.as_rel_ospath().to_str().ok_or(FsError::GeneralFailure)?;
- self.op
- .copy(from_path, to_path)
- .await
- .map_err(convert_error)
- }
- .boxed()
- }
-
- fn rename<'a>(&'a self, from: &'a DavPath, to: &'a DavPath) ->
dav_server::fs::FsFuture<()> {
- async move {
- let from_path = from
- .as_rel_ospath()
- .to_str()
- .ok_or(FsError::GeneralFailure)?;
- let to_path =
to.as_rel_ospath().to_str().ok_or(FsError::GeneralFailure)?;
- if from.is_collection() {
- let _ = self.remove_file(to).await;
- }
- self.op
- .rename(from_path, to_path)
- .await
- .map_err(convert_error)
- }
- .boxed()
- }
-}
-
-impl WebdavFs {
- pub fn new(op: Operator) -> Box<WebdavFs> {
- Box::new(WebdavFs { op })
- }
-}
-
-struct DavStream {
- op: Operator,
- lister: Lister,
-}
-
-impl Stream for DavStream {
- type Item = Box<dyn DavDirEntry>;
-
- fn poll_next(
- self: std::pin::Pin<&mut Self>,
- cx: &mut std::task::Context<'_>,
- ) -> std::task::Poll<Option<Self::Item>> {
- let dav_stream = self.get_mut();
- let lister = Pin::new(&mut dav_stream.lister).get_mut();
-
- match Pin::new(lister).poll_next(cx) {
- Ready(entry) => match entry {
- Some(entry) => {
- let webdav_entry = WebDAVDirEntry::new(entry.unwrap(),
dav_stream.op.clone());
- Ready(Some(Box::new(webdav_entry) as Box<dyn DavDirEntry>))
- }
- None => Ready(None),
- },
- Pending => Pending,
- }
- }
-}
-
-impl DavStream {
- fn new(op: Operator, lister: Lister) -> Self {
- DavStream { op, lister }
- }
-}