Skip to content

Commit

Permalink
refactor(services/webdav): Add WebdavConfig to implement ConfigDeseri…
Browse files Browse the repository at this point in the history
…alizer (#3846)

* refactor(services/webdav): Add WebdavConfig to implement ConfigDeserializer

* fix(services/webdav): resolve conversation
  • Loading branch information
kwaa authored Dec 30, 2023
1 parent 7a14155 commit ad8c51a
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 19 deletions.
2 changes: 2 additions & 0 deletions core/src/services/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ pub use supabase::Supabase;
mod webdav;
#[cfg(feature = "services-webdav")]
pub use webdav::Webdav;
#[cfg(feature = "services-webdav")]
pub use webdav::WebdavConfig;

#[cfg(feature = "services-webhdfs")]
mod webhdfs;
Expand Down
64 changes: 45 additions & 19 deletions core/src/services/webdav/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use http::Request;
use http::Response;
use http::StatusCode;
use log::debug;
use serde::Deserialize;

use super::error::parse_error;
use super::lister::Multistatus;
Expand All @@ -37,25 +38,50 @@ use super::writer::WebdavWriter;
use crate::raw::*;
use crate::*;

/// Config for [WebDAV](https://datatracker.ietf.org/doc/html/rfc4918) backend support.
#[derive(Default, Deserialize)]
#[serde(default)]
#[non_exhaustive]
pub struct WebdavConfig {
/// endpoint of this backend
pub endpoint: Option<String>,
/// username of this backend
pub username: Option<String>,
/// password of this backend
pub password: Option<String>,
/// token of this backend
pub token: Option<String>,
/// root of this backend
pub root: Option<String>,
}

impl Debug for WebdavConfig {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut d = f.debug_struct("WebdavConfig");

d.field("endpoint", &self.endpoint)
.field("username", &self.username)
.field("root", &self.root);

d.finish_non_exhaustive()
}
}

/// [WebDAV](https://datatracker.ietf.org/doc/html/rfc4918) backend support.
#[doc = include_str!("docs.md")]
#[derive(Default)]
pub struct WebdavBuilder {
endpoint: Option<String>,
username: Option<String>,
password: Option<String>,
token: Option<String>,
root: Option<String>,
config: WebdavConfig,
http_client: Option<HttpClient>,
}

impl Debug for WebdavBuilder {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut de = f.debug_struct("Builder");
de.field("endpoint", &self.endpoint);
de.field("root", &self.root);
let mut d = f.debug_struct("WebdavBuilder");

d.field("config", &self.config);

de.finish()
d.finish_non_exhaustive()
}
}

Expand All @@ -64,7 +90,7 @@ impl WebdavBuilder {
///
/// For example: `https://example.com`
pub fn endpoint(&mut self, endpoint: &str) -> &mut Self {
self.endpoint = if endpoint.is_empty() {
self.config.endpoint = if endpoint.is_empty() {
None
} else {
Some(endpoint.to_string())
Expand All @@ -78,7 +104,7 @@ impl WebdavBuilder {
/// default: no password
pub fn username(&mut self, username: &str) -> &mut Self {
if !username.is_empty() {
self.username = Some(username.to_owned());
self.config.username = Some(username.to_owned());
}
self
}
Expand All @@ -88,7 +114,7 @@ impl WebdavBuilder {
/// default: no password
pub fn password(&mut self, password: &str) -> &mut Self {
if !password.is_empty() {
self.password = Some(password.to_owned());
self.config.password = Some(password.to_owned());
}
self
}
Expand All @@ -98,14 +124,14 @@ impl WebdavBuilder {
/// default: no access token
pub fn token(&mut self, token: &str) -> &mut Self {
if !token.is_empty() {
self.token = Some(token.to_owned());
self.config.token = Some(token.to_owned());
}
self
}

/// Set root path of http backend.
pub fn root(&mut self, root: &str) -> &mut Self {
self.root = if root.is_empty() {
self.config.root = if root.is_empty() {
None
} else {
Some(root.to_string())
Expand Down Expand Up @@ -145,7 +171,7 @@ impl Builder for WebdavBuilder {
fn build(&mut self) -> Result<Self::Accessor> {
debug!("backend build started: {:?}", &self);

let endpoint = match &self.endpoint {
let endpoint = match &self.config.endpoint {
Some(v) => v,
None => {
return Err(Error::new(ErrorKind::ConfigInvalid, "endpoint is empty")
Expand All @@ -162,7 +188,7 @@ impl Builder for WebdavBuilder {
// returned in the `href`.
let base_dir = uri.path().trim_end_matches('/');

let root = normalize_root(&self.root.take().unwrap_or_default());
let root = normalize_root(&self.config.root.take().unwrap_or_default());
debug!("backend use root {}", root);

let client = if let Some(client) = self.http_client.take() {
Expand All @@ -175,13 +201,13 @@ impl Builder for WebdavBuilder {
};

let mut auth = None;
if let Some(username) = &self.username {
if let Some(username) = &self.config.username {
auth = Some(format_authorization_by_basic(
username,
self.password.as_deref().unwrap_or_default(),
self.config.password.as_deref().unwrap_or_default(),
)?);
}
if let Some(token) = &self.token {
if let Some(token) = &self.config.token {
auth = Some(format_authorization_by_bearer(token)?)
}

Expand Down
1 change: 1 addition & 0 deletions core/src/services/webdav/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

mod backend;
pub use backend::WebdavBuilder as Webdav;
pub use backend::WebdavConfig;

mod error;
mod lister;
Expand Down

0 comments on commit ad8c51a

Please sign in to comment.