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/opendal.git


The following commit(s) were added to refs/heads/main by this push:
     new 4c1e7cd75 feat(webdav): disable_create_dir for servers without 
PROPFIND (#7177)
4c1e7cd75 is described below

commit 4c1e7cd75e30446a47e40fef184fb8a9018e83d3
Author: Weihang Lo <[email protected]>
AuthorDate: Mon Feb 2 09:39:22 2026 -0500

    feat(webdav): disable_create_dir for servers without PROPFIND (#7177)
    
    Some WebDAV-compatible servers like bazel-remote don't implement the
    full WebDAV protocol. Specifically, they don't support the PROPFIND
    method and don't require explicit directory creation before writing
    files.
    
    Currently, OpenDAL's WebDAV `write()` always calls `webdav_mkcol()`
    before writing to ensure parent directories exist. This uses PROPFIND
    to check directory existence, which fails on servers that don't
    support it. For example, bazel-remote returns `405 Method Not Allowed.
    
    This adds a new `disable_create_dir` configuration option that skips
    the automatic parent directory creation in write operations.
    
    * Builder API:
      ```rust
      let op = Webdav::default()
          .endpoint("http://bazel-remote:8080";)
          .disable_create_dir(true)
          .build()?;
      ```
    
    * Via URI:
      ```
      webdav://bazel-remote:8080?disable_create_dir=true
      ```
    
    * Environment variable:
      ```
      OPENDAL_WEBDAV_DISABLE_CREATE_DIR=true
      ```
---
 core/services/webdav/src/backend.rs | 22 ++++++++++++++++++++--
 core/services/webdav/src/config.rs  | 24 ++++++++++++++++++++++++
 core/services/webdav/src/core.rs    |  3 +++
 3 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/core/services/webdav/src/backend.rs 
b/core/services/webdav/src/backend.rs
index 61929dea7..807c8d525 100644
--- a/core/services/webdav/src/backend.rs
+++ b/core/services/webdav/src/backend.rs
@@ -104,6 +104,21 @@ impl WebdavBuilder {
         self
     }
 
+    /// Disable automatic parent directory creation before write operations.
+    ///
+    /// By default, OpenDAL creates parent directories using MKCOL before 
writing files.
+    /// This requires PROPFIND support to check directory existence.
+    ///
+    /// Some WebDAV-compatible servers (e.g., bazel-remote) don't support 
PROPFIND
+    /// or don't require explicit directory creation. Enable this option to 
skip
+    /// the MKCOL calls and write files directly.
+    ///
+    /// Default: false
+    pub fn disable_create_dir(mut self, disable: bool) -> Self {
+        self.config.disable_create_dir = disable;
+        self
+    }
+
     /// Enable user metadata support via WebDAV PROPPATCH.
     ///
     /// This feature requires the WebDAV server to support RFC4918 PROPPATCH 
method.
@@ -225,6 +240,7 @@ impl Builder for WebdavBuilder {
                 .config
                 .user_metadata_uri
                 .unwrap_or_else(|| DEFAULT_USER_METADATA_URI.to_string()),
+            disable_create_dir: self.config.disable_create_dir,
         });
         Ok(WebdavBackend { core })
     }
@@ -274,8 +290,10 @@ impl Access for WebdavBackend {
     }
 
     async fn write(&self, path: &str, args: OpWrite) -> Result<(RpWrite, 
Self::Writer)> {
-        // Ensure parent path exists
-        self.core.webdav_mkcol(get_parent(path)).await?;
+        // Ensure parent path exists (unless disabled for servers that don't 
support PROPFIND)
+        if !self.core.disable_create_dir {
+            self.core.webdav_mkcol(get_parent(path)).await?;
+        }
 
         Ok((
             RpWrite::default(),
diff --git a/core/services/webdav/src/config.rs 
b/core/services/webdav/src/config.rs
index f37ca1ef4..d09506869 100644
--- a/core/services/webdav/src/config.rs
+++ b/core/services/webdav/src/config.rs
@@ -39,6 +39,17 @@ pub struct WebdavConfig {
     pub root: Option<String>,
     /// WebDAV Service doesn't support copy.
     pub disable_copy: bool,
+    /// Disable automatic parent directory creation before write operations.
+    ///
+    /// By default, OpenDAL creates parent directories using MKCOL before 
writing files.
+    /// This requires PROPFIND support to check directory existence.
+    ///
+    /// Some WebDAV-compatible servers (e.g., bazel-remote) don't support 
PROPFIND
+    /// or don't require explicit directory creation. Enable this option to 
skip
+    /// the MKCOL calls and write files directly.
+    ///
+    /// Default: false
+    pub disable_create_dir: bool,
     /// Enable user metadata support via WebDAV PROPPATCH.
     ///
     /// This feature requires the WebDAV server to support RFC4918 PROPPATCH 
method.
@@ -71,6 +82,7 @@ impl Debug for WebdavConfig {
             .field("username", &self.username)
             .field("root", &self.root)
             .field("disable_copy", &self.disable_copy)
+            .field("disable_create_dir", &self.disable_create_dir)
             .field("enable_user_metadata", &self.enable_user_metadata)
             .field("user_metadata_prefix", &self.user_metadata_prefix)
             .field("user_metadata_uri", &self.user_metadata_uri)
@@ -144,4 +156,16 @@ mod tests {
         let cfg = WebdavConfig::from_uri(&uri).unwrap();
         assert!(cfg.disable_copy);
     }
+
+    #[test]
+    fn from_uri_propagates_disable_create_dir() {
+        let uri = OperatorUri::new(
+            "webdav://dav.example.com",
+            vec![("disable_create_dir".to_string(), "true".to_string())],
+        )
+        .unwrap();
+
+        let cfg = WebdavConfig::from_uri(&uri).unwrap();
+        assert!(cfg.disable_create_dir);
+    }
 }
diff --git a/core/services/webdav/src/core.rs b/core/services/webdav/src/core.rs
index c06af3141..57a52dcba 100644
--- a/core/services/webdav/src/core.rs
+++ b/core/services/webdav/src/core.rs
@@ -93,6 +93,8 @@ pub struct WebdavCore {
     pub user_metadata_prefix: String,
     /// XML namespace URI for user metadata properties.
     pub user_metadata_uri: String,
+    /// Skip automatic parent directory creation before writes.
+    pub disable_create_dir: bool,
 }
 
 impl Debug for WebdavCore {
@@ -102,6 +104,7 @@ impl Debug for WebdavCore {
             .field("root", &self.root)
             .field("user_metadata_prefix", &self.user_metadata_prefix)
             .field("user_metadata_uri", &self.user_metadata_uri)
+            .field("disable_create_dir", &self.disable_create_dir)
             .finish_non_exhaustive()
     }
 }

Reply via email to