You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by xu...@apache.org on 2025/10/14 12:24:45 UTC

(opendal) 03/03: Refactor

This is an automated email from the ASF dual-hosted git repository.

xuanwo pushed a commit to branch cleanup-config
in repository https://gitbox.apache.org/repos/asf/opendal.git

commit 7a2afee81f5123b7e40444b1d16650218c0a2c70
Author: Xuanwo <gi...@xuanwo.io>
AuthorDate: Tue Oct 14 20:24:27 2025 +0800

    Refactor
    
    Signed-off-by: Xuanwo <gi...@xuanwo.io>
---
 core/src/services/aliyun_drive/backend.rs     |  15 +--
 core/src/services/aliyun_drive/config.rs      |  14 +++
 core/src/services/alluxio/backend.rs          |  15 +--
 core/src/services/alluxio/config.rs           |  14 +++
 core/src/services/azblob/backend.rs           |  63 +----------
 core/src/services/azblob/config.rs            |  82 ++++++++++----
 core/src/services/azdls/backend.rs            |  16 +--
 core/src/services/azdls/config.rs             |  14 +++
 core/src/services/azfile/backend.rs           |  16 +--
 core/src/services/azfile/config.rs            |  14 +++
 core/src/services/b2/backend.rs               |  51 +--------
 core/src/services/b2/config.rs                |  48 ++++++++
 core/src/services/cacache/backend.rs          |   8 +-
 core/src/services/cacache/config.rs           |   9 ++
 core/src/services/cloudflare_kv/backend.rs    |  14 +--
 core/src/services/cloudflare_kv/config.rs     |  12 ++
 core/src/services/compfs/backend.rs           |   8 +-
 core/src/services/compfs/config.rs            |   9 ++
 core/src/services/cos/backend.rs              |  50 +--------
 core/src/services/cos/config.rs               |  47 ++++++++
 core/src/services/d1/backend.rs               |  14 +--
 core/src/services/d1/config.rs                |  12 ++
 core/src/services/dashmap/backend.rs          |   8 +-
 core/src/services/dashmap/config.rs           |   9 ++
 core/src/services/dbfs/backend.rs             |   8 +-
 core/src/services/dbfs/config.rs              |   9 ++
 core/src/services/dropbox/builder.rs          |  15 +--
 core/src/services/dropbox/config.rs           |  14 +++
 core/src/services/etcd/backend.rs             |   9 +-
 core/src/services/etcd/config.rs              |   9 ++
 core/src/services/foundationdb/backend.rs     |   9 +-
 core/src/services/foundationdb/config.rs      |   9 ++
 core/src/services/fs/backend.rs               |  45 +-------
 core/src/services/fs/config.rs                |  44 ++++++++
 core/src/services/ftp/backend.rs              |  32 +-----
 core/src/services/ftp/config.rs               |  29 +++++
 core/src/services/gcs/backend.rs              |  53 +--------
 core/src/services/gcs/config.rs               |  71 ++++++++----
 core/src/services/gdrive/builder.rs           |  15 +--
 core/src/services/gdrive/config.rs            |  14 +++
 core/src/services/ghac/backend.rs             |  16 +--
 core/src/services/ghac/config.rs              |  14 +++
 core/src/services/github/backend.rs           |  15 +--
 core/src/services/github/config.rs            |  14 +++
 core/src/services/gridfs/backend.rs           |   9 +-
 core/src/services/gridfs/config.rs            |   9 ++
 core/src/services/hdfs/backend.rs             |   8 +-
 core/src/services/hdfs/config.rs              |   9 ++
 core/src/services/hdfs_native/backend.rs      |   9 +-
 core/src/services/hdfs_native/config.rs       |   9 ++
 core/src/services/http/backend.rs             |  81 +------------
 core/src/services/http/config.rs              |  80 +++++++++++++
 core/src/services/huggingface/backend.rs      |   8 +-
 core/src/services/huggingface/config.rs       |   9 ++
 core/src/services/ipfs/backend.rs             |  15 +--
 core/src/services/ipfs/config.rs              |  14 +++
 core/src/services/ipmfs/builder.rs            |  15 +--
 core/src/services/ipmfs/config.rs             |  14 +++
 core/src/services/koofr/backend.rs            |  15 +--
 core/src/services/koofr/config.rs             |  14 +++
 core/src/services/lakefs/backend.rs           |   8 +-
 core/src/services/lakefs/config.rs            |   9 ++
 core/src/services/memcached/backend.rs        |   9 +-
 core/src/services/memcached/config.rs         |   9 ++
 core/src/services/memory/backend.rs           |  48 +-------
 core/src/services/memory/config.rs            |  38 +++++++
 core/src/services/mini_moka/backend.rs        |   8 +-
 core/src/services/mini_moka/config.rs         |   9 ++
 core/src/services/moka/backend.rs             |  13 +--
 core/src/services/moka/config.rs              |  12 ++
 core/src/services/mongodb/backend.rs          |   9 +-
 core/src/services/mongodb/config.rs           |   9 ++
 core/src/services/monoiofs/backend.rs         |   9 +-
 core/src/services/monoiofs/config.rs          |   9 ++
 core/src/services/mysql/backend.rs            |   9 +-
 core/src/services/mysql/config.rs             |   9 ++
 core/src/services/obs/backend.rs              |  50 +--------
 core/src/services/obs/config.rs               |  47 ++++++++
 core/src/services/onedrive/builder.rs         |  13 +--
 core/src/services/onedrive/config.rs          |  12 ++
 core/src/services/oss/backend.rs              |  51 +--------
 core/src/services/oss/config.rs               |  47 ++++++++
 core/src/services/pcloud/backend.rs           |  15 +--
 core/src/services/pcloud/config.rs            |  14 +++
 core/src/services/persy/backend.rs            |   9 +-
 core/src/services/persy/config.rs             |   9 ++
 core/src/services/postgresql/backend.rs       |   9 +-
 core/src/services/postgresql/config.rs        |   9 ++
 core/src/services/redb/backend.rs             |  14 +--
 core/src/services/redb/config.rs              |  12 ++
 core/src/services/redis/backend.rs            |  74 +-----------
 core/src/services/redis/config.rs             |  35 ++++++
 core/src/services/rocksdb/backend.rs          |   9 +-
 core/src/services/rocksdb/config.rs           |   9 ++
 core/src/services/s3/backend.rs               | 156 +-------------------------
 core/src/services/s3/config.rs                |  45 ++++++++
 core/src/services/seafile/backend.rs          |  15 +--
 core/src/services/seafile/config.rs           |  14 +++
 core/src/services/sftp/backend.rs             |  63 +----------
 core/src/services/sftp/config.rs              |  64 +++++++++++
 core/src/services/sled/backend.rs             |   9 +-
 core/src/services/sled/config.rs              |   9 ++
 core/src/services/sqlite/backend.rs           |   9 +-
 core/src/services/sqlite/config.rs            |   9 ++
 core/src/services/surrealdb/backend.rs        |   9 +-
 core/src/services/surrealdb/config.rs         |   9 ++
 core/src/services/swift/backend.rs            |   8 +-
 core/src/services/swift/config.rs             |   9 ++
 core/src/services/tikv/backend.rs             |   9 +-
 core/src/services/tikv/config.rs              |   9 ++
 core/src/services/upyun/backend.rs            |  49 +-------
 core/src/services/upyun/config.rs             |  46 ++++++++
 core/src/services/vercel_artifacts/builder.rs |  15 +--
 core/src/services/vercel_artifacts/config.rs  |  14 +++
 core/src/services/vercel_blob/backend.rs      |  15 +--
 core/src/services/vercel_blob/config.rs       |  14 +++
 core/src/services/webdav/backend.rs           |  79 +------------
 core/src/services/webdav/config.rs            |  78 +++++++++++++
 core/src/services/webhdfs/backend.rs          |   9 +-
 core/src/services/webhdfs/config.rs           |   9 ++
 core/src/services/yandex_disk/backend.rs      |  15 +--
 core/src/services/yandex_disk/config.rs       |  14 +++
 122 files changed, 1360 insertions(+), 1422 deletions(-)

diff --git a/core/src/services/aliyun_drive/backend.rs b/core/src/services/aliyun_drive/backend.rs
index 220544784..ec79d3a42 100644
--- a/core/src/services/aliyun_drive/backend.rs
+++ b/core/src/services/aliyun_drive/backend.rs
@@ -35,25 +35,14 @@ use super::writer::AliyunDriveWriter;
 use crate::raw::*;
 use crate::services::AliyunDriveConfig;
 use crate::*;
-impl Configurator for AliyunDriveConfig {
-    type Builder = AliyunDriveBuilder;
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        AliyunDriveBuilder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
 
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct AliyunDriveBuilder {
-    config: AliyunDriveConfig,
+    pub(super) config: AliyunDriveConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for AliyunDriveBuilder {
diff --git a/core/src/services/aliyun_drive/config.rs b/core/src/services/aliyun_drive/config.rs
index ed6ae534b..b2939e998 100644
--- a/core/src/services/aliyun_drive/config.rs
+++ b/core/src/services/aliyun_drive/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::AliyunDriveBuilder;
 
 /// Config for Aliyun Drive services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -70,3 +71,16 @@ impl Debug for AliyunDriveConfig {
         d.finish_non_exhaustive()
     }
 }
+
+impl crate::Configurator for AliyunDriveConfig {
+    type Builder = AliyunDriveBuilder;
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        AliyunDriveBuilder {
+            config: self,
+            http_client: None,
+        }
+    }
+}
+
diff --git a/core/src/services/alluxio/backend.rs b/core/src/services/alluxio/backend.rs
index b383ef963..9133e4696 100644
--- a/core/src/services/alluxio/backend.rs
+++ b/core/src/services/alluxio/backend.rs
@@ -32,26 +32,15 @@ use super::writer::AlluxioWriters;
 use crate::raw::*;
 use crate::services::AlluxioConfig;
 use crate::*;
-impl Configurator for AlluxioConfig {
-    type Builder = AlluxioBuilder;
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        AlluxioBuilder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
 
 /// [Alluxio](https://www.alluxio.io/) services support.
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct AlluxioBuilder {
-    config: AlluxioConfig,
+    pub(super) config: AlluxioConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for AlluxioBuilder {
diff --git a/core/src/services/alluxio/config.rs b/core/src/services/alluxio/config.rs
index 0c2c2e176..fce76d333 100644
--- a/core/src/services/alluxio/config.rs
+++ b/core/src/services/alluxio/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::AlluxioBuilder;
 
 /// Config for alluxio services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -48,3 +49,16 @@ impl Debug for AlluxioConfig {
         d.finish_non_exhaustive()
     }
 }
+
+impl crate::Configurator for AlluxioConfig {
+    type Builder = AlluxioBuilder;
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        AlluxioBuilder {
+            config: self,
+            http_client: None,
+        }
+    }
+}
+
diff --git a/core/src/services/azblob/backend.rs b/core/src/services/azblob/backend.rs
index df81c11a7..44cf9025e 100644
--- a/core/src/services/azblob/backend.rs
+++ b/core/src/services/azblob/backend.rs
@@ -41,7 +41,6 @@ use super::writer::AzblobWriter;
 use super::writer::AzblobWriters;
 use crate::raw::*;
 use crate::services::AzblobConfig;
-use crate::types::OperatorUri;
 use crate::*;
 const AZBLOB_BATCH_LIMIT: usize = 256;
 
@@ -57,40 +56,13 @@ impl From<AzureStorageConfig> for AzblobConfig {
     }
 }
 
-impl Configurator for AzblobConfig {
-    type Builder = AzblobBuilder;
-
-    fn from_uri(uri: &OperatorUri) -> Result<Self> {
-        let mut map = uri.options().clone();
-
-        if let Some(container) = uri.name() {
-            map.insert("container".to_string(), container.to_string());
-        }
-
-        if let Some(root) = uri.root() {
-            map.insert("root".to_string(), root.to_string());
-        }
-
-        Self::from_iter(map)
-    }
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        AzblobBuilder {
-            config: self,
-
-            http_client: None,
-        }
-    }
-}
-
 #[doc = include_str!("docs.md")]
 #[derive(Default, Clone)]
 pub struct AzblobBuilder {
-    config: AzblobConfig,
+    pub(super) config: AzblobConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for AzblobBuilder {
@@ -607,34 +579,3 @@ impl Access for AzblobBackend {
         )))
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use crate::Configurator;
-    use crate::types::OperatorUri;
-
-    #[test]
-    fn from_uri_with_host_container() {
-        let uri = OperatorUri::new(
-            "azblob://my-container/path/to/root".parse().unwrap(),
-            Vec::<(String, String)>::new(),
-        )
-        .unwrap();
-        let cfg = AzblobConfig::from_uri(&uri).unwrap();
-        assert_eq!(cfg.container, "my-container");
-        assert_eq!(cfg.root.as_deref(), Some("path/to/root"));
-    }
-
-    #[test]
-    fn from_uri_with_path_container() {
-        let uri = OperatorUri::new(
-            "azblob://my-container/nested/root".parse().unwrap(),
-            Vec::<(String, String)>::new(),
-        )
-        .unwrap();
-        let cfg = AzblobConfig::from_uri(&uri).unwrap();
-        assert_eq!(cfg.container, "my-container");
-        assert_eq!(cfg.root.as_deref(), Some("nested/root"));
-    }
-}
diff --git a/core/src/services/azblob/config.rs b/core/src/services/azblob/config.rs
index 829e725e2..188e1ac50 100644
--- a/core/src/services/azblob/config.rs
+++ b/core/src/services/azblob/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::AzblobBuilder;
 
 /// Azure Storage Blob services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -99,23 +100,51 @@ impl Debug for AzblobConfig {
     }
 }
 
+
+
+impl crate::Configurator for AzblobConfig {
+    type Builder = AzblobBuilder;
+
+    fn from_uri(uri: &crate::types::OperatorUri) -> crate::Result<Self> {
+        let mut map = uri.options().clone();
+
+        if let Some(container) = uri.name() {
+            map.insert("container".to_string(), container.to_string());
+        }
+
+        if let Some(root) = uri.root() {
+            map.insert("root".to_string(), root.to_string());
+        }
+
+        Self::from_iter(map)
+    }
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        AzblobBuilder {
+            config: self,
+
+            http_client: None,
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
+    use crate::Configurator;
+    use crate::types::OperatorUri;
 
     #[test]
     fn test_container_name_aliases() {
-        // Test original container field
         let json = r#"{"container": "test-container"}"#;
         let config: AzblobConfig = serde_json::from_str(json).unwrap();
         assert_eq!(config.container, "test-container");
 
-        // Test azure_container_name alias
         let json = r#"{"azure_container_name": "test-container"}"#;
         let config: AzblobConfig = serde_json::from_str(json).unwrap();
         assert_eq!(config.container, "test-container");
 
-        // Test container_name alias
         let json = r#"{"container_name": "test-container"}"#;
         let config: AzblobConfig = serde_json::from_str(json).unwrap();
         assert_eq!(config.container, "test-container");
@@ -123,45 +152,37 @@ mod tests {
 
     #[test]
     fn test_account_name_aliases() {
-        // Test original account_name field
         let json = r#"{"container": "test", "account_name": "testaccount"}"#;
         let config: AzblobConfig = serde_json::from_str(json).unwrap();
         assert_eq!(config.account_name, Some("testaccount".to_string()));
 
-        // Test azure_storage_account_name alias
-        let json = r#"{"container": "test", "azure_storage_account_name": "testaccount"}"#;
+        let json = r#"{"container": "test", "azure_storage_account_name": "testaccount-azure"}"#;
         let config: AzblobConfig = serde_json::from_str(json).unwrap();
-        assert_eq!(config.account_name, Some("testaccount".to_string()));
+        assert_eq!(config.account_name, Some("testaccount-azure".to_string()));
     }
 
     #[test]
     fn test_account_key_aliases() {
-        // Test original account_key field
         let json = r#"{"container": "test", "account_key": "dGVzdGtleQ=="}"#;
         let config: AzblobConfig = serde_json::from_str(json).unwrap();
         assert_eq!(config.account_key, Some("dGVzdGtleQ==".to_string()));
 
-        // Test azure_storage_account_key alias
         let json = r#"{"container": "test", "azure_storage_account_key": "dGVzdGtleQ=="}"#;
         let config: AzblobConfig = serde_json::from_str(json).unwrap();
         assert_eq!(config.account_key, Some("dGVzdGtleQ==".to_string()));
 
-        // Test azure_storage_access_key alias
         let json = r#"{"container": "test", "azure_storage_access_key": "dGVzdGtleQ=="}"#;
         let config: AzblobConfig = serde_json::from_str(json).unwrap();
         assert_eq!(config.account_key, Some("dGVzdGtleQ==".to_string()));
 
-        // Test azure_storage_master_key alias
         let json = r#"{"container": "test", "azure_storage_master_key": "dGVzdGtleQ=="}"#;
         let config: AzblobConfig = serde_json::from_str(json).unwrap();
         assert_eq!(config.account_key, Some("dGVzdGtleQ==".to_string()));
 
-        // Test access_key alias
         let json = r#"{"container": "test", "access_key": "dGVzdGtleQ=="}"#;
         let config: AzblobConfig = serde_json::from_str(json).unwrap();
         assert_eq!(config.account_key, Some("dGVzdGtleQ==".to_string()));
 
-        // Test master_key alias
         let json = r#"{"container": "test", "master_key": "dGVzdGtleQ=="}"#;
         let config: AzblobConfig = serde_json::from_str(json).unwrap();
         assert_eq!(config.account_key, Some("dGVzdGtleQ==".to_string()));
@@ -169,22 +190,18 @@ mod tests {
 
     #[test]
     fn test_sas_token_aliases() {
-        // Test original sas_token field
         let json = r#"{"container": "test", "sas_token": "test-token"}"#;
         let config: AzblobConfig = serde_json::from_str(json).unwrap();
         assert_eq!(config.sas_token, Some("test-token".to_string()));
 
-        // Test azure_storage_sas_key alias
         let json = r#"{"container": "test", "azure_storage_sas_key": "test-token"}"#;
         let config: AzblobConfig = serde_json::from_str(json).unwrap();
         assert_eq!(config.sas_token, Some("test-token".to_string()));
 
-        // Test azure_storage_sas_token alias
         let json = r#"{"container": "test", "azure_storage_sas_token": "test-token"}"#;
         let config: AzblobConfig = serde_json::from_str(json).unwrap();
         assert_eq!(config.sas_token, Some("test-token".to_string()));
 
-        // Test sas_key alias
         let json = r#"{"container": "test", "sas_key": "test-token"}"#;
         let config: AzblobConfig = serde_json::from_str(json).unwrap();
         assert_eq!(config.sas_token, Some("test-token".to_string()));
@@ -192,7 +209,6 @@ mod tests {
 
     #[test]
     fn test_endpoint_aliases() {
-        // Test original endpoint field
         let json = r#"{"container": "test", "endpoint": "https://test.blob.core.windows.net"}"#;
         let config: AzblobConfig = serde_json::from_str(json).unwrap();
         assert_eq!(
@@ -200,7 +216,6 @@ mod tests {
             Some("https://test.blob.core.windows.net".to_string())
         );
 
-        // Test azure_storage_endpoint alias
         let json = r#"{"container": "test", "azure_storage_endpoint": "https://test.blob.core.windows.net"}"#;
         let config: AzblobConfig = serde_json::from_str(json).unwrap();
         assert_eq!(
@@ -208,13 +223,36 @@ mod tests {
             Some("https://test.blob.core.windows.net".to_string())
         );
 
-        // Test azure_endpoint alias
-        let json =
-            r#"{"container": "test", "azure_endpoint": "https://test.blob.core.windows.net"}"#;
+        let json = r#"{"container": "test", "azure_endpoint": "https://test.blob.core.windows.net"}"#;
         let config: AzblobConfig = serde_json::from_str(json).unwrap();
         assert_eq!(
             config.endpoint,
             Some("https://test.blob.core.windows.net".to_string())
         );
     }
+
+    #[test]
+    fn from_uri_with_host_container() {
+        let uri = OperatorUri::new(
+            "azblob://my-container/path/to/root".parse().unwrap(),
+            Vec::<(String, String)>::new(),
+        )
+        .unwrap();
+        let cfg = AzblobConfig::from_uri(&uri).unwrap();
+        assert_eq!(cfg.container, "my-container");
+        assert_eq!(cfg.root.as_deref(), Some("path/to/root"));
+    }
+
+    #[test]
+    fn from_uri_with_path_container() {
+        let uri = OperatorUri::new(
+            "azblob://my-container/nested/root".parse().unwrap(),
+            Vec::<(String, String)>::new(),
+        )
+        .unwrap();
+        let cfg = AzblobConfig::from_uri(&uri).unwrap();
+        assert_eq!(cfg.container, "my-container");
+        assert_eq!(cfg.root.as_deref(), Some("nested/root"));
+    }
 }
+
diff --git a/core/src/services/azdls/backend.rs b/core/src/services/azdls/backend.rs
index 629823e8f..1d255c9f3 100644
--- a/core/src/services/azdls/backend.rs
+++ b/core/src/services/azdls/backend.rs
@@ -53,26 +53,14 @@ impl From<AzureStorageConfig> for AzdlsConfig {
     }
 }
 
-impl Configurator for AzdlsConfig {
-    type Builder = AzdlsBuilder;
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        AzdlsBuilder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
-
 /// Azure Data Lake Storage Gen2 Support.
 #[doc = include_str!("docs.md")]
 #[derive(Default, Clone)]
 pub struct AzdlsBuilder {
-    config: AzdlsConfig,
+    pub(super) config: AzdlsConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for AzdlsBuilder {
diff --git a/core/src/services/azdls/config.rs b/core/src/services/azdls/config.rs
index 9f8178a01..98200f8b1 100644
--- a/core/src/services/azdls/config.rs
+++ b/core/src/services/azdls/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::AzdlsBuilder;
 
 /// Azure Data Lake Storage Gen2 Support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -87,3 +88,16 @@ impl Debug for AzdlsConfig {
         ds.finish()
     }
 }
+
+impl crate::Configurator for AzdlsConfig {
+    type Builder = AzdlsBuilder;
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        AzdlsBuilder {
+            config: self,
+            http_client: None,
+        }
+    }
+}
+
diff --git a/core/src/services/azfile/backend.rs b/core/src/services/azfile/backend.rs
index 6ab518926..257496477 100644
--- a/core/src/services/azfile/backend.rs
+++ b/core/src/services/azfile/backend.rs
@@ -49,26 +49,14 @@ impl From<AzureStorageConfig> for AzfileConfig {
     }
 }
 
-impl Configurator for AzfileConfig {
-    type Builder = AzfileBuilder;
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        AzfileBuilder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
-
 /// Azure File services support.
 #[doc = include_str!("docs.md")]
 #[derive(Default, Clone)]
 pub struct AzfileBuilder {
-    config: AzfileConfig,
+    pub(super) config: AzfileConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for AzfileBuilder {
diff --git a/core/src/services/azfile/config.rs b/core/src/services/azfile/config.rs
index 8d9d1527a..d394a63a0 100644
--- a/core/src/services/azfile/config.rs
+++ b/core/src/services/azfile/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::AzfileBuilder;
 
 /// Azure File services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -59,3 +60,16 @@ impl Debug for AzfileConfig {
         ds.finish()
     }
 }
+
+impl crate::Configurator for AzfileConfig {
+    type Builder = AzfileBuilder;
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        AzfileBuilder {
+            config: self,
+            http_client: None,
+        }
+    }
+}
+
diff --git a/core/src/services/b2/backend.rs b/core/src/services/b2/backend.rs
index d545fce5a..d865ab861 100644
--- a/core/src/services/b2/backend.rs
+++ b/core/src/services/b2/backend.rs
@@ -37,42 +37,16 @@ use super::writer::B2Writer;
 use super::writer::B2Writers;
 use crate::raw::*;
 use crate::services::B2Config;
-use crate::types::OperatorUri;
 use crate::*;
-impl Configurator for B2Config {
-    type Builder = B2Builder;
-
-    fn from_uri(uri: &OperatorUri) -> Result<Self> {
-        let mut map = uri.options().clone();
-
-        if let Some(name) = uri.name() {
-            map.insert("bucket".to_string(), name.to_string());
-        }
-
-        if let Some(root) = uri.root() {
-            map.insert("root".to_string(), root.to_string());
-        }
-
-        Self::from_iter(map)
-    }
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        B2Builder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
 
 /// [b2](https://www.backblaze.com/cloud-storage) services support.
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct B2Builder {
-    config: B2Config,
+    pub(super) config: B2Config,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for B2Builder {
@@ -447,24 +421,3 @@ impl Access for B2Backend {
         }
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use crate::Configurator;
-    use crate::types::OperatorUri;
-
-    #[test]
-    fn from_uri_extracts_bucket_and_root() {
-        let uri = OperatorUri::new(
-            "b2://example-bucket/path/to/root".parse().unwrap(),
-            vec![("bucket_id".to_string(), "bucket-id".to_string())],
-        )
-        .unwrap();
-
-        let cfg = B2Config::from_uri(&uri).unwrap();
-        assert_eq!(cfg.bucket, "example-bucket");
-        assert_eq!(cfg.root.as_deref(), Some("path/to/root"));
-        assert_eq!(cfg.bucket_id, "bucket-id");
-    }
-}
diff --git a/core/src/services/b2/config.rs b/core/src/services/b2/config.rs
index d5da9b0a8..caf22f9a9 100644
--- a/core/src/services/b2/config.rs
+++ b/core/src/services/b2/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::B2Builder;
 
 /// Config for backblaze b2 services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -62,3 +63,50 @@ impl Debug for B2Config {
         d.finish_non_exhaustive()
     }
 }
+
+impl crate::Configurator for B2Config {
+    type Builder = B2Builder;
+
+    fn from_uri(uri: &crate::types::OperatorUri) -> crate::Result<Self> {
+        let mut map = uri.options().clone();
+
+        if let Some(name) = uri.name() {
+            map.insert("bucket".to_string(), name.to_string());
+        }
+
+        if let Some(root) = uri.root() {
+            map.insert("root".to_string(), root.to_string());
+        }
+
+        Self::from_iter(map)
+    }
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        B2Builder {
+            config: self,
+            http_client: None,
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::Configurator;
+    use crate::types::OperatorUri;
+
+    #[test]
+    fn from_uri_extracts_bucket_and_root() {
+        let uri = OperatorUri::new(
+            "b2://example-bucket/path/to/root".parse().unwrap(),
+            vec![("bucket_id".to_string(), "bucket-id".to_string())],
+        )
+        .unwrap();
+
+        let cfg = B2Config::from_uri(&uri).unwrap();
+        assert_eq!(cfg.bucket, "example-bucket");
+        assert_eq!(cfg.root.as_deref(), Some("path/to/root"));
+        assert_eq!(cfg.bucket_id, "bucket-id");
+    }
+}
diff --git a/core/src/services/cacache/backend.rs b/core/src/services/cacache/backend.rs
index eeecb57b8..af910922f 100644
--- a/core/src/services/cacache/backend.rs
+++ b/core/src/services/cacache/backend.rs
@@ -25,18 +25,12 @@ use super::CACACHE_SCHEME;
 use super::core::CacacheCore;
 use super::delete::CacacheDeleter;
 use super::writer::CacacheWriter;
-impl Configurator for CacacheConfig {
-    type Builder = CacacheBuilder;
-    fn into_builder(self) -> Self::Builder {
-        CacacheBuilder { config: self }
-    }
-}
 
 /// cacache service support.
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct CacacheBuilder {
-    config: CacacheConfig,
+    pub(super) config: CacacheConfig,
 }
 
 impl CacacheBuilder {
diff --git a/core/src/services/cacache/config.rs b/core/src/services/cacache/config.rs
index 1d01a3863..6733f0f6f 100644
--- a/core/src/services/cacache/config.rs
+++ b/core/src/services/cacache/config.rs
@@ -19,6 +19,7 @@ use std::fmt::Debug;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::CacacheBuilder;
 
 /// cacache service support.
 #[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -26,3 +27,11 @@ pub struct CacacheConfig {
     /// That path to the cacache data directory.
     pub datadir: Option<String>,
 }
+
+impl crate::Configurator for CacacheConfig {
+    type Builder = CacacheBuilder;
+    fn into_builder(self) -> Self::Builder {
+        CacacheBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/cloudflare_kv/backend.rs b/core/src/services/cloudflare_kv/backend.rs
index 5c42e1b2f..25abf8f6e 100644
--- a/core/src/services/cloudflare_kv/backend.rs
+++ b/core/src/services/cloudflare_kv/backend.rs
@@ -34,23 +34,13 @@ use crate::*;
 use bytes::Buf;
 use http::StatusCode;
 
-impl Configurator for CloudflareKvConfig {
-    type Builder = CloudflareKvBuilder;
-    fn into_builder(self) -> Self::Builder {
-        CloudflareKvBuilder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
-
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct CloudflareKvBuilder {
-    config: CloudflareKvConfig,
+    pub(super) config: CloudflareKvConfig,
 
     /// The HTTP client used to communicate with CloudFlare.
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for CloudflareKvBuilder {
diff --git a/core/src/services/cloudflare_kv/config.rs b/core/src/services/cloudflare_kv/config.rs
index 576e84bbf..c97eb0746 100644
--- a/core/src/services/cloudflare_kv/config.rs
+++ b/core/src/services/cloudflare_kv/config.rs
@@ -21,6 +21,7 @@ use std::time::Duration;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::CloudflareKvBuilder;
 
 /// Cloudflare KV Service Support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -53,3 +54,14 @@ impl Debug for CloudflareKvConfig {
         ds.finish()
     }
 }
+
+impl crate::Configurator for CloudflareKvConfig {
+    type Builder = CloudflareKvBuilder;
+    fn into_builder(self) -> Self::Builder {
+        CloudflareKvBuilder {
+            config: self,
+            http_client: None,
+        }
+    }
+}
+
diff --git a/core/src/services/compfs/backend.rs b/core/src/services/compfs/backend.rs
index 592055d22..8aa0c1705 100644
--- a/core/src/services/compfs/backend.rs
+++ b/core/src/services/compfs/backend.rs
@@ -31,17 +31,11 @@ use crate::raw::oio::OneShotDeleter;
 use crate::raw::*;
 use crate::services::CompfsConfig;
 use crate::*;
-impl Configurator for CompfsConfig {
-    type Builder = CompfsBuilder;
-    fn into_builder(self) -> Self::Builder {
-        CompfsBuilder { config: self }
-    }
-}
 
 /// [`compio`]-based file system support.
 #[derive(Debug, Clone, Default)]
 pub struct CompfsBuilder {
-    config: CompfsConfig,
+    pub(super) config: CompfsConfig,
 }
 
 impl CompfsBuilder {
diff --git a/core/src/services/compfs/config.rs b/core/src/services/compfs/config.rs
index 49cc68098..d2ca25937 100644
--- a/core/src/services/compfs/config.rs
+++ b/core/src/services/compfs/config.rs
@@ -19,6 +19,7 @@ use std::fmt::Debug;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::CompfsBuilder;
 
 /// compio-based file system support.
 #[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -28,3 +29,11 @@ pub struct CompfsConfig {
     /// All operations will happen under this root.
     pub root: Option<String>,
 }
+
+impl crate::Configurator for CompfsConfig {
+    type Builder = CompfsBuilder;
+    fn into_builder(self) -> Self::Builder {
+        CompfsBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/cos/backend.rs b/core/src/services/cos/backend.rs
index 780e1aa78..a526c6838 100644
--- a/core/src/services/cos/backend.rs
+++ b/core/src/services/cos/backend.rs
@@ -38,43 +38,16 @@ use super::writer::CosWriters;
 use crate::raw::oio::PageLister;
 use crate::raw::*;
 use crate::services::CosConfig;
-use crate::types::OperatorUri;
 use crate::*;
-impl Configurator for CosConfig {
-    type Builder = CosBuilder;
-
-    fn from_uri(uri: &OperatorUri) -> Result<Self> {
-        let mut map = uri.options().clone();
-
-        if let Some(name) = uri.name() {
-            map.insert("bucket".to_string(), name.to_string());
-        }
-
-        if let Some(root) = uri.root() {
-            map.insert("root".to_string(), root.to_string());
-        }
-
-        Self::from_iter(map)
-    }
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        CosBuilder {
-            config: self,
-
-            http_client: None,
-        }
-    }
-}
 
 /// Tencent-Cloud COS services support.
 #[doc = include_str!("docs.md")]
 #[derive(Default, Clone)]
 pub struct CosBuilder {
-    config: CosConfig,
+    pub(super) config: CosConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for CosBuilder {
@@ -455,22 +428,3 @@ impl Access for CosBackend {
         )))
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use crate::Configurator;
-    use crate::types::OperatorUri;
-
-    #[test]
-    fn from_uri_extracts_bucket_and_root() {
-        let uri = OperatorUri::new(
-            "cos://example-bucket/path/to/root".parse().unwrap(),
-            Vec::<(String, String)>::new(),
-        )
-        .unwrap();
-        let cfg = CosConfig::from_uri(&uri).unwrap();
-        assert_eq!(cfg.bucket.as_deref(), Some("example-bucket"));
-        assert_eq!(cfg.root.as_deref(), Some("path/to/root"));
-    }
-}
diff --git a/core/src/services/cos/config.rs b/core/src/services/cos/config.rs
index 87436a84b..02e662a68 100644
--- a/core/src/services/cos/config.rs
+++ b/core/src/services/cos/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::CosBuilder;
 
 /// Tencent-Cloud COS services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -52,3 +53,49 @@ impl Debug for CosConfig {
             .finish_non_exhaustive()
     }
 }
+
+impl crate::Configurator for CosConfig {
+    type Builder = CosBuilder;
+
+    fn from_uri(uri: &crate::types::OperatorUri) -> crate::Result<Self> {
+        let mut map = uri.options().clone();
+
+        if let Some(name) = uri.name() {
+            map.insert("bucket".to_string(), name.to_string());
+        }
+
+        if let Some(root) = uri.root() {
+            map.insert("root".to_string(), root.to_string());
+        }
+
+        Self::from_iter(map)
+    }
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        CosBuilder {
+            config: self,
+
+            http_client: None,
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::Configurator;
+    use crate::types::OperatorUri;
+
+    #[test]
+    fn from_uri_extracts_bucket_and_root() {
+        let uri = OperatorUri::new(
+            "cos://example-bucket/path/to/root".parse().unwrap(),
+            Vec::<(String, String)>::new(),
+        )
+        .unwrap();
+        let cfg = CosConfig::from_uri(&uri).unwrap();
+        assert_eq!(cfg.bucket.as_deref(), Some("example-bucket"));
+        assert_eq!(cfg.root.as_deref(), Some("path/to/root"));
+    }
+}
diff --git a/core/src/services/d1/backend.rs b/core/src/services/d1/backend.rs
index 3e414bb62..dd195a1f4 100644
--- a/core/src/services/d1/backend.rs
+++ b/core/src/services/d1/backend.rs
@@ -31,22 +31,12 @@ use crate::raw::*;
 use crate::services::D1Config;
 use crate::*;
 
-impl Configurator for D1Config {
-    type Builder = D1Builder;
-    fn into_builder(self) -> Self::Builder {
-        D1Builder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
-
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct D1Builder {
-    config: D1Config,
+    pub(super) config: D1Config,
 
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for D1Builder {
diff --git a/core/src/services/d1/config.rs b/core/src/services/d1/config.rs
index 2e8b111ef..dbd6663dd 100644
--- a/core/src/services/d1/config.rs
+++ b/core/src/services/d1/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::D1Builder;
 
 /// Config for [Cloudflare D1](https://developers.cloudflare.com/d1) backend support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -53,3 +54,14 @@ impl Debug for D1Config {
         ds.finish_non_exhaustive()
     }
 }
+
+impl crate::Configurator for D1Config {
+    type Builder = D1Builder;
+    fn into_builder(self) -> Self::Builder {
+        D1Builder {
+            config: self,
+            http_client: None,
+        }
+    }
+}
+
diff --git a/core/src/services/dashmap/backend.rs b/core/src/services/dashmap/backend.rs
index 2b0c540a8..778884e18 100644
--- a/core/src/services/dashmap/backend.rs
+++ b/core/src/services/dashmap/backend.rs
@@ -31,18 +31,12 @@ use crate::raw::oio;
 use crate::raw::*;
 use crate::services::DashmapConfig;
 use crate::*;
-impl Configurator for DashmapConfig {
-    type Builder = DashmapBuilder;
-    fn into_builder(self) -> Self::Builder {
-        DashmapBuilder { config: self }
-    }
-}
 
 /// [dashmap](https://github.com/xacrimon/dashmap) backend support.
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct DashmapBuilder {
-    config: DashmapConfig,
+    pub(super) config: DashmapConfig,
 }
 
 impl Debug for DashmapBuilder {
diff --git a/core/src/services/dashmap/config.rs b/core/src/services/dashmap/config.rs
index 7e9833d9c..412f894fb 100644
--- a/core/src/services/dashmap/config.rs
+++ b/core/src/services/dashmap/config.rs
@@ -18,6 +18,7 @@
 use serde::Deserialize;
 use serde::Serialize;
 use std::fmt::Debug;
+use super::backend::DashmapBuilder;
 
 /// Config for Dashmap services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -35,3 +36,11 @@ impl Debug for DashmapConfig {
             .finish_non_exhaustive()
     }
 }
+
+impl crate::Configurator for DashmapConfig {
+    type Builder = DashmapBuilder;
+    fn into_builder(self) -> Self::Builder {
+        DashmapBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/dbfs/backend.rs b/core/src/services/dbfs/backend.rs
index 2a6ed5a8b..2a8422a2d 100644
--- a/core/src/services/dbfs/backend.rs
+++ b/core/src/services/dbfs/backend.rs
@@ -33,18 +33,12 @@ use super::writer::DbfsWriter;
 use crate::raw::*;
 use crate::services::DbfsConfig;
 use crate::*;
-impl Configurator for DbfsConfig {
-    type Builder = DbfsBuilder;
-    fn into_builder(self) -> Self::Builder {
-        DbfsBuilder { config: self }
-    }
-}
 
 /// [Dbfs](https://docs.databricks.com/api/azure/workspace/dbfs)'s REST API support.
 #[doc = include_str!("docs.md")]
 #[derive(Default, Clone)]
 pub struct DbfsBuilder {
-    config: DbfsConfig,
+    pub(super) config: DbfsConfig,
 }
 
 impl Debug for DbfsBuilder {
diff --git a/core/src/services/dbfs/config.rs b/core/src/services/dbfs/config.rs
index 65498511c..df057b7db 100644
--- a/core/src/services/dbfs/config.rs
+++ b/core/src/services/dbfs/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::DbfsBuilder;
 
 /// [Dbfs](https://docs.databricks.com/api/azure/workspace/dbfs)'s REST API support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -46,3 +47,11 @@ impl Debug for DbfsConfig {
         ds.finish()
     }
 }
+
+impl crate::Configurator for DbfsConfig {
+    type Builder = DbfsBuilder;
+    fn into_builder(self) -> Self::Builder {
+        DbfsBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/dropbox/builder.rs b/core/src/services/dropbox/builder.rs
index 520b28004..d580137e2 100644
--- a/core/src/services/dropbox/builder.rs
+++ b/core/src/services/dropbox/builder.rs
@@ -27,26 +27,15 @@ use super::core::DropboxSigner;
 use crate::raw::*;
 use crate::services::DropboxConfig;
 use crate::*;
-impl Configurator for DropboxConfig {
-    type Builder = DropboxBuilder;
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        DropboxBuilder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
 
 /// [Dropbox](https://www.dropbox.com/) backend support.
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct DropboxBuilder {
-    config: DropboxConfig,
+    pub(super) config: DropboxConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for DropboxBuilder {
diff --git a/core/src/services/dropbox/config.rs b/core/src/services/dropbox/config.rs
index 4882e3a0c..5f9ffa57b 100644
--- a/core/src/services/dropbox/config.rs
+++ b/core/src/services/dropbox/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::builder::DropboxBuilder;
 
 /// Config for [Dropbox](https://www.dropbox.com/) backend support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -45,3 +46,16 @@ impl Debug for DropboxConfig {
             .finish_non_exhaustive()
     }
 }
+
+impl crate::Configurator for DropboxConfig {
+    type Builder = DropboxBuilder;
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        DropboxBuilder {
+            config: self,
+            http_client: None,
+        }
+    }
+}
+
diff --git a/core/src/services/etcd/backend.rs b/core/src/services/etcd/backend.rs
index 3dcd0a0c8..ab6903828 100644
--- a/core/src/services/etcd/backend.rs
+++ b/core/src/services/etcd/backend.rs
@@ -35,18 +35,11 @@ use crate::raw::*;
 use crate::services::EtcdConfig;
 use crate::*;
 
-impl Configurator for EtcdConfig {
-    type Builder = EtcdBuilder;
-    fn into_builder(self) -> Self::Builder {
-        EtcdBuilder { config: self }
-    }
-}
-
 /// [Etcd](https://etcd.io/) services support.
 #[doc = include_str!("docs.md")]
 #[derive(Clone, Default)]
 pub struct EtcdBuilder {
-    config: EtcdConfig,
+    pub(super) config: EtcdConfig,
 }
 
 impl Debug for EtcdBuilder {
diff --git a/core/src/services/etcd/config.rs b/core/src/services/etcd/config.rs
index f592f99f5..286667a4f 100644
--- a/core/src/services/etcd/config.rs
+++ b/core/src/services/etcd/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::EtcdBuilder;
 
 /// Config for Etcd services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -84,3 +85,11 @@ impl Debug for EtcdConfig {
         ds.finish()
     }
 }
+
+impl crate::Configurator for EtcdConfig {
+    type Builder = EtcdBuilder;
+    fn into_builder(self) -> Self::Builder {
+        EtcdBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/foundationdb/backend.rs b/core/src/services/foundationdb/backend.rs
index f9022b152..151de6c47 100644
--- a/core/src/services/foundationdb/backend.rs
+++ b/core/src/services/foundationdb/backend.rs
@@ -31,17 +31,10 @@ use crate::raw::*;
 use crate::services::FoundationdbConfig;
 use crate::*;
 
-impl Configurator for FoundationdbConfig {
-    type Builder = FoundationdbBuilder;
-    fn into_builder(self) -> Self::Builder {
-        FoundationdbBuilder { config: self }
-    }
-}
-
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct FoundationdbBuilder {
-    config: FoundationdbConfig,
+    pub(super) config: FoundationdbConfig,
 }
 
 impl FoundationdbBuilder {
diff --git a/core/src/services/foundationdb/config.rs b/core/src/services/foundationdb/config.rs
index 924db518f..1e9756947 100644
--- a/core/src/services/foundationdb/config.rs
+++ b/core/src/services/foundationdb/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::FoundationdbBuilder;
 
 /// [foundationdb](https://www.foundationdb.org/) service support.
 ///Config for FoundationDB.
@@ -43,3 +44,11 @@ impl Debug for FoundationdbConfig {
         ds.finish()
     }
 }
+
+impl crate::Configurator for FoundationdbConfig {
+    type Builder = FoundationdbBuilder;
+    fn into_builder(self) -> Self::Builder {
+        FoundationdbBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/fs/backend.rs b/core/src/services/fs/backend.rs
index 9e67c530f..9e210e2cc 100644
--- a/core/src/services/fs/backend.rs
+++ b/core/src/services/fs/backend.rs
@@ -29,37 +29,13 @@ use super::writer::FsWriter;
 use super::writer::FsWriters;
 use crate::raw::*;
 use crate::services::FsConfig;
-use crate::types::OperatorUri;
 use crate::*;
-impl Configurator for FsConfig {
-    type Builder = FsBuilder;
-
-    fn from_uri(uri: &OperatorUri) -> Result<Self> {
-        let mut map = uri.options().clone();
-
-        if let Some(value) = match (uri.name(), uri.root()) {
-            (Some(name), Some(rest)) if !rest.is_empty() => Some(format!("/{}/{}", name, rest)),
-            (Some(name), _) => Some(format!("/{}", name)),
-            (None, Some(rest)) if !rest.is_empty() => Some(format!("/{}", rest)),
-            (None, Some(rest)) => Some(rest.to_string()),
-            _ => None,
-        } {
-            map.insert("root".to_string(), value);
-        }
-
-        Self::from_iter(map)
-    }
-
-    fn into_builder(self) -> Self::Builder {
-        FsBuilder { config: self }
-    }
-}
 
 /// POSIX file system support.
 #[doc = include_str!("docs.md")]
 #[derive(Default, Debug)]
 pub struct FsBuilder {
-    config: FsConfig,
+    pub(super) config: FsConfig,
 }
 
 impl FsBuilder {
@@ -289,22 +265,3 @@ impl Access for FsBackend {
         Ok(RpRename::default())
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use crate::Configurator;
-    use crate::types::OperatorUri;
-    use http::Uri;
-
-    #[test]
-    fn from_uri_extracts_root() {
-        let uri = OperatorUri::new(
-            Uri::from_static("fs://tmp/data"),
-            Vec::<(String, String)>::new(),
-        )
-        .unwrap();
-        let cfg = FsConfig::from_uri(&uri).unwrap();
-        assert_eq!(cfg.root.as_deref(), Some("/tmp/data"));
-    }
-}
diff --git a/core/src/services/fs/config.rs b/core/src/services/fs/config.rs
index eb501ee8c..60748dfa7 100644
--- a/core/src/services/fs/config.rs
+++ b/core/src/services/fs/config.rs
@@ -19,6 +19,7 @@ use std::fmt::Debug;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::FsBuilder;
 
 /// config for file system
 #[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -31,3 +32,46 @@ pub struct FsConfig {
     /// tmp dir for atomic write
     pub atomic_write_dir: Option<String>,
 }
+
+impl crate::Configurator for FsConfig {
+    type Builder = FsBuilder;
+
+    fn from_uri(uri: &crate::types::OperatorUri) -> crate::Result<Self> {
+        let mut map = uri.options().clone();
+
+        if let Some(value) = match (uri.name(), uri.root()) {
+            (Some(name), Some(rest)) if !rest.is_empty() => Some(format!("/{}/{}", name, rest)),
+            (Some(name), _) => Some(format!("/{}", name)),
+            (None, Some(rest)) if !rest.is_empty() => Some(format!("/{}", rest)),
+            (None, Some(rest)) => Some(rest.to_string()),
+            _ => None,
+        } {
+            map.insert("root".to_string(), value);
+        }
+
+        Self::from_iter(map)
+    }
+
+    fn into_builder(self) -> Self::Builder {
+        FsBuilder { config: self }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::Configurator;
+    use crate::types::OperatorUri;
+    use http::Uri;
+
+    #[test]
+    fn from_uri_extracts_root() {
+        let uri = OperatorUri::new(
+            Uri::from_static("fs://tmp/data"),
+            Vec::<(String, String)>::new(),
+        )
+        .unwrap();
+        let cfg = FsConfig::from_uri(&uri).unwrap();
+        assert_eq!(cfg.root.as_deref(), Some("/tmp/data"));
+    }
+}
diff --git a/core/src/services/ftp/backend.rs b/core/src/services/ftp/backend.rs
index 9195c033a..1e314d873 100644
--- a/core/src/services/ftp/backend.rs
+++ b/core/src/services/ftp/backend.rs
@@ -39,40 +39,13 @@ use super::reader::FtpReader;
 use super::writer::FtpWriter;
 use crate::raw::*;
 use crate::services::FtpConfig;
-use crate::types::OperatorUri;
 use crate::*;
-impl Configurator for FtpConfig {
-    type Builder = FtpBuilder;
-
-    fn from_uri(uri: &OperatorUri) -> Result<Self> {
-        let authority = uri.authority().ok_or_else(|| {
-            Error::new(ErrorKind::ConfigInvalid, "uri authority is required")
-                .with_context("service", Scheme::Ftp)
-        })?;
-
-        let mut map = uri.options().clone();
-        map.insert(
-            "endpoint".to_string(),
-            format!("{FTP_SCHEME}://{authority}"),
-        );
-
-        if let Some(root) = uri.root() {
-            map.insert("root".to_string(), root.to_string());
-        }
-
-        Self::from_iter(map)
-    }
-
-    fn into_builder(self) -> Self::Builder {
-        FtpBuilder { config: self }
-    }
-}
 
 /// FTP and FTPS services support.
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct FtpBuilder {
-    config: FtpConfig,
+    pub(super) config: FtpConfig,
 }
 
 impl Debug for FtpBuilder {
@@ -377,8 +350,7 @@ impl FtpBackend {
 mod build_test {
     use super::FtpBuilder;
     use crate::services::FtpConfig;
-    use crate::types::OperatorUri;
-    use crate::*;
+        use crate::*;
 
     #[test]
     fn test_build() {
diff --git a/core/src/services/ftp/config.rs b/core/src/services/ftp/config.rs
index f2942ad3b..e5f2337ae 100644
--- a/core/src/services/ftp/config.rs
+++ b/core/src/services/ftp/config.rs
@@ -20,6 +20,8 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::FTP_SCHEME;
+use super::backend::FtpBuilder;
 
 /// Config for Ftp services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -44,3 +46,30 @@ impl Debug for FtpConfig {
             .finish_non_exhaustive()
     }
 }
+
+impl crate::Configurator for FtpConfig {
+    type Builder = FtpBuilder;
+
+    fn from_uri(uri: &crate::types::OperatorUri) -> crate::Result<Self> {
+        let authority = uri.authority().ok_or_else(|| {
+            crate::Error::new(crate::ErrorKind::ConfigInvalid, "uri authority is required")
+                .with_context("service", crate::Scheme::Ftp)
+        })?;
+
+        let mut map = uri.options().clone();
+        map.insert(
+            "endpoint".to_string(),
+            format!("{FTP_SCHEME}://{authority}"),
+        );
+
+        if let Some(root) = uri.root() {
+            map.insert("root".to_string(), root.to_string());
+        }
+
+        Self::from_iter(map)
+    }
+
+    fn into_builder(self) -> Self::Builder {
+        FtpBuilder { config: self }
+    }
+}
diff --git a/core/src/services/gcs/backend.rs b/core/src/services/gcs/backend.rs
index 6ba521f16..aa90f603b 100644
--- a/core/src/services/gcs/backend.rs
+++ b/core/src/services/gcs/backend.rs
@@ -37,47 +37,19 @@ use super::writer::GcsWriters;
 use crate::raw::oio::BatchDeleter;
 use crate::raw::*;
 use crate::services::GcsConfig;
-use crate::types::OperatorUri;
 use crate::*;
 const DEFAULT_GCS_ENDPOINT: &str = "https://storage.googleapis.com";
 const DEFAULT_GCS_SCOPE: &str = "https://www.googleapis.com/auth/devstorage.read_write";
 
-impl Configurator for GcsConfig {
-    type Builder = GcsBuilder;
-
-    fn from_uri(uri: &OperatorUri) -> Result<Self> {
-        let mut map = uri.options().clone();
-
-        if let Some(name) = uri.name() {
-            map.insert("bucket".to_string(), name.to_string());
-        }
-
-        if let Some(root) = uri.root() {
-            map.insert("root".to_string(), root.to_string());
-        }
-
-        Self::from_iter(map)
-    }
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        GcsBuilder {
-            config: self,
-            http_client: None,
-            customized_token_loader: None,
-        }
-    }
-}
-
 /// [Google Cloud Storage](https://cloud.google.com/storage) services support.
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct GcsBuilder {
-    config: GcsConfig,
+    pub(super) config: GcsConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
-    customized_token_loader: Option<Box<dyn GoogleTokenLoad>>,
+    pub(super) http_client: Option<HttpClient>,
+    pub(super) customized_token_loader: Option<Box<dyn GoogleTokenLoad>>,
 }
 
 impl Debug for GcsBuilder {
@@ -512,22 +484,3 @@ impl Access for GcsBackend {
         )))
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use crate::Configurator;
-    use crate::types::OperatorUri;
-
-    #[test]
-    fn from_uri_extracts_bucket_and_root() {
-        let uri = OperatorUri::new(
-            "gcs://example-bucket/path/to/root".parse().unwrap(),
-            Vec::<(String, String)>::new(),
-        )
-        .unwrap();
-        let cfg = GcsConfig::from_uri(&uri).unwrap();
-        assert_eq!(cfg.bucket, "example-bucket");
-        assert_eq!(cfg.root.as_deref(), Some("path/to/root"));
-    }
-}
diff --git a/core/src/services/gcs/config.rs b/core/src/services/gcs/config.rs
index 3e440e493..bc9b830d3 100644
--- a/core/src/services/gcs/config.rs
+++ b/core/src/services/gcs/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::GcsBuilder;
 
 /// [Google Cloud Storage](https://cloud.google.com/storage) services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -83,23 +84,51 @@ impl Debug for GcsConfig {
     }
 }
 
+
+
+impl crate::Configurator for GcsConfig {
+    type Builder = GcsBuilder;
+
+    fn from_uri(uri: &crate::types::OperatorUri) -> crate::Result<Self> {
+        let mut map = uri.options().clone();
+
+        if let Some(name) = uri.name() {
+            map.insert("bucket".to_string(), name.to_string());
+        }
+
+        if let Some(root) = uri.root() {
+            map.insert("root".to_string(), root.to_string());
+        }
+
+        Self::from_iter(map)
+    }
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        GcsBuilder {
+            config: self,
+            http_client: None,
+            customized_token_loader: None,
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
+    use crate::Configurator;
+    use crate::types::OperatorUri;
 
     #[test]
     fn test_bucket_aliases() {
-        // Test google_bucket alias
         let config_json = r#"{"google_bucket": "test-bucket"}"#;
         let config: GcsConfig = serde_json::from_str(config_json).unwrap();
         assert_eq!("test-bucket", config.bucket);
 
-        // Test google_bucket_name alias
         let config_json = r#"{"google_bucket_name": "test-bucket-name"}"#;
         let config: GcsConfig = serde_json::from_str(config_json).unwrap();
         assert_eq!("test-bucket-name", config.bucket);
 
-        // Test bucket_name alias
         let config_json = r#"{"bucket_name": "test-bucket-alias"}"#;
         let config: GcsConfig = serde_json::from_str(config_json).unwrap();
         assert_eq!("test-bucket-alias", config.bucket);
@@ -107,36 +136,25 @@ mod tests {
 
     #[test]
     fn test_service_account_aliases() {
-        // Test google_service_account alias
         let config_json = r#"{"google_service_account": "/path/to/sa.json"}"#;
         let config: GcsConfig = serde_json::from_str(config_json).unwrap();
         assert_eq!(Some("/path/to/sa.json".to_string()), config.service_account);
 
-        // Test google_service_account_path alias
         let config_json = r#"{"google_service_account_path": "/path/to/sa2.json"}"#;
         let config: GcsConfig = serde_json::from_str(config_json).unwrap();
-        assert_eq!(
-            Some("/path/to/sa2.json".to_string()),
-            config.service_account
-        );
+        assert_eq!(Some("/path/to/sa2.json".to_string()), config.service_account);
 
-        // Test service_account_path alias
         let config_json = r#"{"service_account_path": "/path/to/sa3.json"}"#;
         let config: GcsConfig = serde_json::from_str(config_json).unwrap();
-        assert_eq!(
-            Some("/path/to/sa3.json".to_string()),
-            config.service_account
-        );
+        assert_eq!(Some("/path/to/sa3.json".to_string()), config.service_account);
     }
 
     #[test]
     fn test_credential_aliases() {
-        // Test google_service_account_key alias
         let config_json = r#"{"google_service_account_key": "key-content"}"#;
         let config: GcsConfig = serde_json::from_str(config_json).unwrap();
         assert_eq!(Some("key-content".to_string()), config.credential);
 
-        // Test service_account_key alias
         let config_json = r#"{"service_account_key": "key-content-2"}"#;
         let config: GcsConfig = serde_json::from_str(config_json).unwrap();
         assert_eq!(Some("key-content-2".to_string()), config.credential);
@@ -144,25 +162,32 @@ mod tests {
 
     #[test]
     fn test_credential_path_aliases() {
-        // Test google_application_credentials alias
         let config_json = r#"{"google_application_credentials": "/path/to/app.json"}"#;
         let config: GcsConfig = serde_json::from_str(config_json).unwrap();
-        assert_eq!(
-            Some("/path/to/app.json".to_string()),
-            config.credential_path
-        );
+        assert_eq!(Some("/path/to/app.json".to_string()), config.credential_path);
     }
 
     #[test]
     fn test_allow_anonymous_aliases() {
-        // Test google_skip_signature alias
         let config_json = r#"{"google_skip_signature": true}"#;
         let config: GcsConfig = serde_json::from_str(config_json).unwrap();
         assert!(config.allow_anonymous);
 
-        // Test skip_signature alias
         let config_json = r#"{"skip_signature": true}"#;
         let config: GcsConfig = serde_json::from_str(config_json).unwrap();
         assert!(config.allow_anonymous);
     }
+
+    #[test]
+    fn from_uri_extracts_bucket_and_root() {
+        let uri = OperatorUri::new(
+            "gcs://example-bucket/path/to/root".parse().unwrap(),
+            Vec::<(String, String)>::new(),
+        )
+        .unwrap();
+        let cfg = GcsConfig::from_uri(&uri).unwrap();
+        assert_eq!(cfg.bucket, "example-bucket");
+        assert_eq!(cfg.root.as_deref(), Some("path/to/root"));
+    }
 }
+
diff --git a/core/src/services/gdrive/builder.rs b/core/src/services/gdrive/builder.rs
index 9b604d102..e519e175f 100644
--- a/core/src/services/gdrive/builder.rs
+++ b/core/src/services/gdrive/builder.rs
@@ -35,26 +35,15 @@ use crate::raw::Timestamp;
 use crate::raw::normalize_root;
 use crate::services::GdriveConfig;
 use crate::*;
-impl Configurator for GdriveConfig {
-    type Builder = GdriveBuilder;
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        GdriveBuilder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
 
 /// [GoogleDrive](https://drive.google.com/) backend support.
 #[derive(Default)]
 #[doc = include_str!("docs.md")]
 pub struct GdriveBuilder {
-    config: GdriveConfig,
+    pub(super) config: GdriveConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for GdriveBuilder {
diff --git a/core/src/services/gdrive/config.rs b/core/src/services/gdrive/config.rs
index 6a217e0e6..00b468ec5 100644
--- a/core/src/services/gdrive/config.rs
+++ b/core/src/services/gdrive/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::builder::GdriveBuilder;
 
 /// [GoogleDrive](https://drive.google.com/) configuration.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -45,3 +46,16 @@ impl Debug for GdriveConfig {
             .finish_non_exhaustive()
     }
 }
+
+impl crate::Configurator for GdriveConfig {
+    type Builder = GdriveBuilder;
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        GdriveBuilder {
+            config: self,
+            http_client: None,
+        }
+    }
+}
+
diff --git a/core/src/services/ghac/backend.rs b/core/src/services/ghac/backend.rs
index c63677ece..6ac4c6f99 100644
--- a/core/src/services/ghac/backend.rs
+++ b/core/src/services/ghac/backend.rs
@@ -48,26 +48,14 @@ fn value_or_env(
     })
 }
 
-impl Configurator for GhacConfig {
-    type Builder = GhacBuilder;
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        GhacBuilder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
-
 /// GitHub Action Cache Services support.
 #[doc = include_str!("docs.md")]
 #[derive(Debug, Default)]
 pub struct GhacBuilder {
-    config: GhacConfig,
+    pub(super) config: GhacConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl GhacBuilder {
diff --git a/core/src/services/ghac/config.rs b/core/src/services/ghac/config.rs
index b1f655e7f..4d3ae66e4 100644
--- a/core/src/services/ghac/config.rs
+++ b/core/src/services/ghac/config.rs
@@ -19,6 +19,7 @@ use std::fmt::Debug;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::GhacBuilder;
 
 /// Config for GitHub Action Cache Services support.
 #[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -34,3 +35,16 @@ pub struct GhacConfig {
     /// The runtime token for ghac service.
     pub runtime_token: Option<String>,
 }
+
+impl crate::Configurator for GhacConfig {
+    type Builder = GhacBuilder;
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        GhacBuilder {
+            config: self,
+            http_client: None,
+        }
+    }
+}
+
diff --git a/core/src/services/github/backend.rs b/core/src/services/github/backend.rs
index 7faa1f5c6..3801c66bf 100644
--- a/core/src/services/github/backend.rs
+++ b/core/src/services/github/backend.rs
@@ -35,26 +35,15 @@ use super::writer::GithubWriters;
 use crate::raw::*;
 use crate::services::GithubConfig;
 use crate::*;
-impl Configurator for GithubConfig {
-    type Builder = GithubBuilder;
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        GithubBuilder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
 
 /// [github contents](https://docs.github.com/en/rest/repos/contents?apiVersion=2022-11-28#create-or-update-file-contents) services support.
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct GithubBuilder {
-    config: GithubConfig,
+    pub(super) config: GithubConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for GithubBuilder {
diff --git a/core/src/services/github/config.rs b/core/src/services/github/config.rs
index 3c89686ab..54ac0cd80 100644
--- a/core/src/services/github/config.rs
+++ b/core/src/services/github/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::GithubBuilder;
 
 /// Config for GitHub services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -57,3 +58,16 @@ impl Debug for GithubConfig {
         d.finish_non_exhaustive()
     }
 }
+
+impl crate::Configurator for GithubConfig {
+    type Builder = GithubBuilder;
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        GithubBuilder {
+            config: self,
+            http_client: None,
+        }
+    }
+}
+
diff --git a/core/src/services/gridfs/backend.rs b/core/src/services/gridfs/backend.rs
index ec9433a4a..85eb3c268 100644
--- a/core/src/services/gridfs/backend.rs
+++ b/core/src/services/gridfs/backend.rs
@@ -27,17 +27,10 @@ use crate::raw::adapters::kv;
 use crate::raw::*;
 use crate::*;
 
-impl Configurator for GridfsConfig {
-    type Builder = GridfsBuilder;
-    fn into_builder(self) -> Self::Builder {
-        GridfsBuilder { config: self }
-    }
-}
-
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct GridfsBuilder {
-    config: GridfsConfig,
+    pub(super) config: GridfsConfig,
 }
 
 impl Debug for GridfsBuilder {
diff --git a/core/src/services/gridfs/config.rs b/core/src/services/gridfs/config.rs
index cd5f84250..ff2992cd6 100644
--- a/core/src/services/gridfs/config.rs
+++ b/core/src/services/gridfs/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::GridfsBuilder;
 
 /// Config for Grid file system support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -48,3 +49,11 @@ impl Debug for GridfsConfig {
             .finish()
     }
 }
+
+impl crate::Configurator for GridfsConfig {
+    type Builder = GridfsBuilder;
+    fn into_builder(self) -> Self::Builder {
+        GridfsBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/hdfs/backend.rs b/core/src/services/hdfs/backend.rs
index 269042e1e..b3705e4c0 100644
--- a/core/src/services/hdfs/backend.rs
+++ b/core/src/services/hdfs/backend.rs
@@ -32,17 +32,11 @@ use super::writer::HdfsWriter;
 use crate::raw::*;
 use crate::services::HdfsConfig;
 use crate::*;
-impl Configurator for HdfsConfig {
-    type Builder = HdfsBuilder;
-    fn into_builder(self) -> Self::Builder {
-        HdfsBuilder { config: self }
-    }
-}
 
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct HdfsBuilder {
-    config: HdfsConfig,
+    pub(super) config: HdfsConfig,
 }
 
 impl Debug for HdfsBuilder {
diff --git a/core/src/services/hdfs/config.rs b/core/src/services/hdfs/config.rs
index ba1e6f593..c8401dca9 100644
--- a/core/src/services/hdfs/config.rs
+++ b/core/src/services/hdfs/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::HdfsBuilder;
 
 /// [Hadoop Distributed File System (HDFSâ„¢)](https://hadoop.apache.org/) support.
 ///
@@ -57,3 +58,11 @@ impl Debug for HdfsConfig {
             .finish_non_exhaustive()
     }
 }
+
+impl crate::Configurator for HdfsConfig {
+    type Builder = HdfsBuilder;
+    fn into_builder(self) -> Self::Builder {
+        HdfsBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/hdfs_native/backend.rs b/core/src/services/hdfs_native/backend.rs
index 364759d86..70136e6a1 100644
--- a/core/src/services/hdfs_native/backend.rs
+++ b/core/src/services/hdfs_native/backend.rs
@@ -34,17 +34,10 @@ use crate::services::HdfsNativeConfig;
 use crate::*;
 /// [Hadoop Distributed File System (HDFSâ„¢)](https://hadoop.apache.org/) support.
 /// Using [Native Rust HDFS client](https://github.com/Kimahriman/hdfs-native).
-impl Configurator for HdfsNativeConfig {
-    type Builder = HdfsNativeBuilder;
-    fn into_builder(self) -> Self::Builder {
-        HdfsNativeBuilder { config: self }
-    }
-}
-
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct HdfsNativeBuilder {
-    config: HdfsNativeConfig,
+    pub(super) config: HdfsNativeConfig,
 }
 
 impl Debug for HdfsNativeBuilder {
diff --git a/core/src/services/hdfs_native/config.rs b/core/src/services/hdfs_native/config.rs
index fcfe19a2c..6b9b2be75 100644
--- a/core/src/services/hdfs_native/config.rs
+++ b/core/src/services/hdfs_native/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::HdfsNativeBuilder;
 
 /// Config for HdfsNative services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -43,3 +44,11 @@ impl Debug for HdfsNativeConfig {
             .finish_non_exhaustive()
     }
 }
+
+impl crate::Configurator for HdfsNativeConfig {
+    type Builder = HdfsNativeBuilder;
+    fn into_builder(self) -> Self::Builder {
+        HdfsNativeBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/http/backend.rs b/core/src/services/http/backend.rs
index 0f62af61a..2df44ce62 100644
--- a/core/src/services/http/backend.rs
+++ b/core/src/services/http/backend.rs
@@ -28,47 +28,16 @@ use super::core::HttpCore;
 use super::error::parse_error;
 use crate::raw::*;
 use crate::services::HttpConfig;
-use crate::types::OperatorUri;
 use crate::*;
-impl Configurator for HttpConfig {
-    type Builder = HttpBuilder;
-
-    fn from_uri(uri: &OperatorUri) -> Result<Self> {
-        let authority = uri.authority().ok_or_else(|| {
-            Error::new(ErrorKind::ConfigInvalid, "uri authority is required")
-                .with_context("service", Scheme::Http)
-        })?;
-
-        let mut map = uri.options().clone();
-        map.insert(
-            "endpoint".to_string(),
-            format!("{}://{}", uri.scheme(), authority),
-        );
-
-        if let Some(root) = uri.root() {
-            map.insert("root".to_string(), root.to_string());
-        }
-
-        Self::from_iter(map)
-    }
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        HttpBuilder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
 
 /// HTTP Read-only service support like [Nginx](https://www.nginx.com/) and [Caddy](https://caddyserver.com/).
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct HttpBuilder {
-    config: HttpConfig,
+    pub(super) config: HttpConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for HttpBuilder {
@@ -309,49 +278,3 @@ impl Access for HttpBackend {
         )))
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn from_uri_sets_endpoint_and_root() {
-        let uri = OperatorUri::new(
-            "http://example.com/static/assets".parse().unwrap(),
-            Vec::<(String, String)>::new(),
-        )
-        .unwrap();
-
-        let cfg = HttpConfig::from_uri(&uri).unwrap();
-        assert_eq!(cfg.endpoint.as_deref(), Some("http://example.com"));
-        assert_eq!(cfg.root.as_deref(), Some("static/assets"));
-    }
-
-    #[test]
-    fn from_uri_preserves_query_options() {
-        let uri = OperatorUri::new(
-            "http://cdn.example.com/data?token=abc123".parse().unwrap(),
-            Vec::<(String, String)>::new(),
-        )
-        .unwrap();
-        let cfg = HttpConfig::from_uri(&uri).unwrap();
-
-        assert_eq!(cfg.endpoint.as_deref(), Some("http://cdn.example.com"));
-        assert_eq!(cfg.token.as_deref(), Some("abc123"));
-    }
-
-    #[test]
-    fn from_uri_ignores_endpoint_override() {
-        let uri = OperatorUri::new(
-            "http://example.com/data".parse().unwrap(),
-            vec![(
-                "endpoint".to_string(),
-                "https://cdn.example.com".to_string(),
-            )],
-        )
-        .unwrap();
-        let cfg = HttpConfig::from_uri(&uri).unwrap();
-
-        assert_eq!(cfg.endpoint.as_deref(), Some("http://example.com"));
-    }
-}
diff --git a/core/src/services/http/config.rs b/core/src/services/http/config.rs
index 3f8681edd..d3c377e44 100644
--- a/core/src/services/http/config.rs
+++ b/core/src/services/http/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::HttpBuilder;
 
 /// Config for Http service support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -47,3 +48,82 @@ impl Debug for HttpConfig {
         de.finish_non_exhaustive()
     }
 }
+
+impl crate::Configurator for HttpConfig {
+    type Builder = HttpBuilder;
+
+    fn from_uri(uri: &crate::types::OperatorUri) -> crate::Result<Self> {
+        let authority = uri.authority().ok_or_else(|| {
+            crate::Error::new(crate::ErrorKind::ConfigInvalid, "uri authority is required")
+                .with_context("service", crate::Scheme::Http)
+        })?;
+
+        let mut map = uri.options().clone();
+        map.insert(
+            "endpoint".to_string(),
+            format!("{}://{}", uri.scheme(), authority),
+        );
+
+        if let Some(root) = uri.root() {
+            map.insert("root".to_string(), root.to_string());
+        }
+
+        Self::from_iter(map)
+    }
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        HttpBuilder {
+            config: self,
+            http_client: None,
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::Configurator;
+    use crate::types::OperatorUri;
+
+    #[test]
+    fn from_uri_sets_endpoint_and_root() {
+        let uri = OperatorUri::new(
+            "http://example.com/static/assets".parse().unwrap(),
+            Vec::<(String, String)>::new(),
+        )
+        .unwrap();
+
+        let cfg = HttpConfig::from_uri(&uri).unwrap();
+        assert_eq!(cfg.endpoint.as_deref(), Some("http://example.com"));
+        assert_eq!(cfg.root.as_deref(), Some("static/assets"));
+    }
+
+    #[test]
+    fn from_uri_preserves_query_options() {
+        let uri = OperatorUri::new(
+            "http://cdn.example.com/data?token=abc123".parse().unwrap(),
+            Vec::<(String, String)>::new(),
+        )
+        .unwrap();
+        let cfg = HttpConfig::from_uri(&uri).unwrap();
+
+        assert_eq!(cfg.endpoint.as_deref(), Some("http://cdn.example.com"));
+        assert_eq!(cfg.token.as_deref(), Some("abc123"));
+    }
+
+    #[test]
+    fn from_uri_ignores_endpoint_override() {
+        let uri = OperatorUri::new(
+            "http://example.com/data".parse().unwrap(),
+            vec![(
+                "endpoint".to_string(),
+                "https://cdn.example.com".to_string(),
+            )],
+        )
+        .unwrap();
+        let cfg = HttpConfig::from_uri(&uri).unwrap();
+
+        assert_eq!(cfg.endpoint.as_deref(), Some("http://example.com"));
+    }
+}
diff --git a/core/src/services/huggingface/backend.rs b/core/src/services/huggingface/backend.rs
index b81b763f7..b4b44c2e4 100644
--- a/core/src/services/huggingface/backend.rs
+++ b/core/src/services/huggingface/backend.rs
@@ -32,18 +32,12 @@ use super::lister::HuggingfaceLister;
 use crate::raw::*;
 use crate::services::HuggingfaceConfig;
 use crate::*;
-impl Configurator for HuggingfaceConfig {
-    type Builder = HuggingfaceBuilder;
-    fn into_builder(self) -> Self::Builder {
-        HuggingfaceBuilder { config: self }
-    }
-}
 
 /// [Huggingface](https://huggingface.co/docs/huggingface_hub/package_reference/hf_api)'s API support.
 #[doc = include_str!("docs.md")]
 #[derive(Default, Clone)]
 pub struct HuggingfaceBuilder {
-    config: HuggingfaceConfig,
+    pub(super) config: HuggingfaceConfig,
 }
 
 impl Debug for HuggingfaceBuilder {
diff --git a/core/src/services/huggingface/config.rs b/core/src/services/huggingface/config.rs
index 3d79996d8..ee24969f8 100644
--- a/core/src/services/huggingface/config.rs
+++ b/core/src/services/huggingface/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::HuggingfaceBuilder;
 
 /// Configuration for Huggingface service support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -73,3 +74,11 @@ impl Debug for HuggingfaceConfig {
         ds.finish()
     }
 }
+
+impl crate::Configurator for HuggingfaceConfig {
+    type Builder = HuggingfaceBuilder;
+    fn into_builder(self) -> Self::Builder {
+        HuggingfaceBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/ipfs/backend.rs b/core/src/services/ipfs/backend.rs
index c82bda2f1..209e2951b 100644
--- a/core/src/services/ipfs/backend.rs
+++ b/core/src/services/ipfs/backend.rs
@@ -31,26 +31,15 @@ use super::ipld::PBNode;
 use crate::raw::*;
 use crate::services::IpfsConfig;
 use crate::*;
-impl Configurator for IpfsConfig {
-    type Builder = IpfsBuilder;
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        IpfsBuilder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
 
 /// IPFS file system support based on [IPFS HTTP Gateway](https://docs.ipfs.tech/concepts/ipfs-gateway/).
 #[doc = include_str!("docs.md")]
 #[derive(Default, Clone, Debug)]
 pub struct IpfsBuilder {
-    config: IpfsConfig,
+    pub(super) config: IpfsConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl IpfsBuilder {
diff --git a/core/src/services/ipfs/config.rs b/core/src/services/ipfs/config.rs
index 535815283..cb46fce32 100644
--- a/core/src/services/ipfs/config.rs
+++ b/core/src/services/ipfs/config.rs
@@ -19,6 +19,7 @@ use std::fmt::Debug;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::IpfsBuilder;
 
 /// Config for IPFS file system support.
 #[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -30,3 +31,16 @@ pub struct IpfsConfig {
     /// IPFS root.
     pub root: Option<String>,
 }
+
+impl crate::Configurator for IpfsConfig {
+    type Builder = IpfsBuilder;
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        IpfsBuilder {
+            config: self,
+            http_client: None,
+        }
+    }
+}
+
diff --git a/core/src/services/ipmfs/builder.rs b/core/src/services/ipmfs/builder.rs
index 02172c960..e0557e7a4 100644
--- a/core/src/services/ipmfs/builder.rs
+++ b/core/src/services/ipmfs/builder.rs
@@ -25,17 +25,6 @@ use super::core::IpmfsCore;
 use crate::raw::*;
 use crate::services::IpmfsConfig;
 use crate::*;
-impl Configurator for IpmfsConfig {
-    type Builder = IpmfsBuilder;
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        IpmfsBuilder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
 
 /// IPFS file system support based on [IPFS MFS](https://docs.ipfs.tech/concepts/file-systems/) API.
 ///
@@ -79,10 +68,10 @@ impl Configurator for IpmfsConfig {
 /// ```
 #[derive(Default, Debug)]
 pub struct IpmfsBuilder {
-    config: IpmfsConfig,
+    pub(super) config: IpmfsConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl IpmfsBuilder {
diff --git a/core/src/services/ipmfs/config.rs b/core/src/services/ipmfs/config.rs
index b24919c07..80efc04f0 100644
--- a/core/src/services/ipmfs/config.rs
+++ b/core/src/services/ipmfs/config.rs
@@ -19,6 +19,7 @@ use std::fmt::Debug;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::builder::IpmfsBuilder;
 
 /// Config for IPFS MFS support.
 #[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -30,3 +31,16 @@ pub struct IpmfsConfig {
     /// Endpoint for ipfs.
     pub endpoint: Option<String>,
 }
+
+impl crate::Configurator for IpmfsConfig {
+    type Builder = IpmfsBuilder;
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        IpmfsBuilder {
+            config: self,
+            http_client: None,
+        }
+    }
+}
+
diff --git a/core/src/services/koofr/backend.rs b/core/src/services/koofr/backend.rs
index 491e1e387..52c431e49 100644
--- a/core/src/services/koofr/backend.rs
+++ b/core/src/services/koofr/backend.rs
@@ -38,26 +38,15 @@ use super::writer::KoofrWriters;
 use crate::raw::*;
 use crate::services::KoofrConfig;
 use crate::*;
-impl Configurator for KoofrConfig {
-    type Builder = KoofrBuilder;
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        KoofrBuilder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
 
 /// [Koofr](https://app.koofr.net/) services support.
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct KoofrBuilder {
-    config: KoofrConfig,
+    pub(super) config: KoofrConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for KoofrBuilder {
diff --git a/core/src/services/koofr/config.rs b/core/src/services/koofr/config.rs
index 3587b4372..c38244d2c 100644
--- a/core/src/services/koofr/config.rs
+++ b/core/src/services/koofr/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::KoofrBuilder;
 
 /// Config for Koofr services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -48,3 +49,16 @@ impl Debug for KoofrConfig {
         ds.finish()
     }
 }
+
+impl crate::Configurator for KoofrConfig {
+    type Builder = KoofrBuilder;
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        KoofrBuilder {
+            config: self,
+            http_client: None,
+        }
+    }
+}
+
diff --git a/core/src/services/lakefs/backend.rs b/core/src/services/lakefs/backend.rs
index 41bca1e02..fefae65b9 100644
--- a/core/src/services/lakefs/backend.rs
+++ b/core/src/services/lakefs/backend.rs
@@ -34,18 +34,12 @@ use super::writer::LakefsWriter;
 use crate::raw::*;
 use crate::services::LakefsConfig;
 use crate::*;
-impl Configurator for LakefsConfig {
-    type Builder = LakefsBuilder;
-    fn into_builder(self) -> Self::Builder {
-        LakefsBuilder { config: self }
-    }
-}
 
 /// [Lakefs](https://docs.lakefs.io/reference/api.html#/)'s API support.
 #[doc = include_str!("docs.md")]
 #[derive(Default, Clone)]
 pub struct LakefsBuilder {
-    config: LakefsConfig,
+    pub(super) config: LakefsConfig,
 }
 
 impl Debug for LakefsBuilder {
diff --git a/core/src/services/lakefs/config.rs b/core/src/services/lakefs/config.rs
index eed964ea5..220077778 100644
--- a/core/src/services/lakefs/config.rs
+++ b/core/src/services/lakefs/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::LakefsBuilder;
 
 /// Configuration for Lakefs service support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -79,3 +80,11 @@ impl Debug for LakefsConfig {
         ds.finish()
     }
 }
+
+impl crate::Configurator for LakefsConfig {
+    type Builder = LakefsBuilder;
+    fn into_builder(self) -> Self::Builder {
+        LakefsBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/memcached/backend.rs b/core/src/services/memcached/backend.rs
index 23e5d2870..5cdde5a0d 100644
--- a/core/src/services/memcached/backend.rs
+++ b/core/src/services/memcached/backend.rs
@@ -27,18 +27,11 @@ use crate::raw::*;
 use crate::services::MemcachedConfig;
 use crate::*;
 
-impl Configurator for MemcachedConfig {
-    type Builder = MemcachedBuilder;
-    fn into_builder(self) -> Self::Builder {
-        MemcachedBuilder { config: self }
-    }
-}
-
 /// [Memcached](https://memcached.org/) service support.
 #[doc = include_str!("docs.md")]
 #[derive(Clone, Default)]
 pub struct MemcachedBuilder {
-    config: MemcachedConfig,
+    pub(super) config: MemcachedConfig,
 }
 
 impl MemcachedBuilder {
diff --git a/core/src/services/memcached/config.rs b/core/src/services/memcached/config.rs
index f0b5815ff..e0f25fd0c 100644
--- a/core/src/services/memcached/config.rs
+++ b/core/src/services/memcached/config.rs
@@ -20,6 +20,7 @@ use std::time::Duration;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::MemcachedBuilder;
 
 /// Config for MemCached services support
 #[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -41,3 +42,11 @@ pub struct MemcachedConfig {
     /// The default ttl for put operations.
     pub default_ttl: Option<Duration>,
 }
+
+impl crate::Configurator for MemcachedConfig {
+    type Builder = MemcachedBuilder;
+    fn into_builder(self) -> Self::Builder {
+        MemcachedBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/memory/backend.rs b/core/src/services/memory/backend.rs
index 1e65f5419..1966a25cf 100644
--- a/core/src/services/memory/backend.rs
+++ b/core/src/services/memory/backend.rs
@@ -26,32 +26,13 @@ use super::writer::MemoryWriter;
 use crate::raw::oio;
 use crate::raw::*;
 use crate::services::MemoryConfig;
-use crate::types::OperatorUri;
 use crate::*;
-impl Configurator for MemoryConfig {
-    type Builder = MemoryBuilder;
-
-    fn from_uri(uri: &OperatorUri) -> Result<Self> {
-        let mut map = uri.options().clone();
-        if !map.contains_key("root") {
-            if let Some(root) = uri.root().filter(|v| !v.is_empty()) {
-                map.insert("root".to_string(), root.to_string());
-            }
-        }
-
-        Self::from_iter(map)
-    }
-
-    fn into_builder(self) -> Self::Builder {
-        MemoryBuilder { config: self }
-    }
-}
 
 /// In memory service support. (BTreeMap Based)
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct MemoryBuilder {
-    config: MemoryConfig,
+    pub(super) config: MemoryConfig,
 }
 
 impl MemoryBuilder {
@@ -186,30 +167,3 @@ impl Access for MemoryAccessor {
         Ok((RpList::default(), lister))
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use crate::Configurator;
-    use crate::types::OperatorUri;
-
-    #[test]
-    fn test_accessor_metadata_name() {
-        let b1 = MemoryBuilder::default().build().unwrap();
-        assert_eq!(b1.info().name(), b1.info().name());
-
-        let b2 = MemoryBuilder::default().build().unwrap();
-        assert_ne!(b1.info().name(), b2.info().name())
-    }
-
-    #[test]
-    fn from_uri_extracts_root() {
-        let uri = OperatorUri::new(
-            "memory://localhost/path/to/root".parse().unwrap(),
-            Vec::<(String, String)>::new(),
-        )
-        .unwrap();
-        let cfg = MemoryConfig::from_uri(&uri).unwrap();
-        assert_eq!(cfg.root.as_deref(), Some("path/to/root"));
-    }
-}
diff --git a/core/src/services/memory/config.rs b/core/src/services/memory/config.rs
index 31321de41..de00b15fa 100644
--- a/core/src/services/memory/config.rs
+++ b/core/src/services/memory/config.rs
@@ -19,6 +19,7 @@ use std::fmt::Debug;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::MemoryBuilder;
 
 /// Config for memory.
 #[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -28,3 +29,40 @@ pub struct MemoryConfig {
     /// root of the backend.
     pub root: Option<String>,
 }
+
+impl crate::Configurator for MemoryConfig {
+    type Builder = MemoryBuilder;
+
+    fn from_uri(uri: &crate::types::OperatorUri) -> crate::Result<Self> {
+        let mut map = uri.options().clone();
+        if !map.contains_key("root") {
+            if let Some(root) = uri.root().filter(|v| !v.is_empty()) {
+                map.insert("root".to_string(), root.to_string());
+            }
+        }
+
+        Self::from_iter(map)
+    }
+
+    fn into_builder(self) -> Self::Builder {
+        MemoryBuilder { config: self }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::Configurator;
+    use crate::types::OperatorUri;
+
+    #[test]
+    fn from_uri_extracts_root() {
+        let uri = OperatorUri::new(
+            "memory://localhost/path/to/root".parse().unwrap(),
+            Vec::<(String, String)>::new(),
+        )
+        .unwrap();
+        let cfg = MemoryConfig::from_uri(&uri).unwrap();
+        assert_eq!(cfg.root.as_deref(), Some("path/to/root"));
+    }
+}
diff --git a/core/src/services/mini_moka/backend.rs b/core/src/services/mini_moka/backend.rs
index 67f768b2a..1256f8f2e 100644
--- a/core/src/services/mini_moka/backend.rs
+++ b/core/src/services/mini_moka/backend.rs
@@ -32,18 +32,12 @@ use crate::raw::oio::HierarchyLister;
 use crate::raw::*;
 use crate::services::MiniMokaConfig;
 use crate::*;
-impl Configurator for MiniMokaConfig {
-    type Builder = MiniMokaBuilder;
-    fn into_builder(self) -> Self::Builder {
-        MiniMokaBuilder { config: self }
-    }
-}
 
 /// [mini-moka](https://github.com/moka-rs/mini-moka) backend support.
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct MiniMokaBuilder {
-    config: MiniMokaConfig,
+    pub(super) config: MiniMokaConfig,
 }
 
 impl Debug for MiniMokaBuilder {
diff --git a/core/src/services/mini_moka/config.rs b/core/src/services/mini_moka/config.rs
index eddfe6d0a..87c313efa 100644
--- a/core/src/services/mini_moka/config.rs
+++ b/core/src/services/mini_moka/config.rs
@@ -21,6 +21,7 @@ use std::time::Duration;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::MiniMokaBuilder;
 
 /// Config for mini-moka support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -54,3 +55,11 @@ impl Debug for MiniMokaConfig {
             .finish()
     }
 }
+
+impl crate::Configurator for MiniMokaConfig {
+    type Builder = MiniMokaBuilder;
+    fn into_builder(self) -> Self::Builder {
+        MiniMokaBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/moka/backend.rs b/core/src/services/moka/backend.rs
index a1a3ef5e5..d83c6a8aa 100644
--- a/core/src/services/moka/backend.rs
+++ b/core/src/services/moka/backend.rs
@@ -31,15 +31,6 @@ use crate::raw::oio;
 use crate::raw::*;
 use crate::services::MokaConfig;
 use crate::*;
-impl Configurator for MokaConfig {
-    type Builder = MokaBuilder;
-    fn into_builder(self) -> Self::Builder {
-        MokaBuilder {
-            config: self,
-            ..Default::default()
-        }
-    }
-}
 
 /// Type alias of [`moka::future::Cache`](https://docs.rs/moka/latest/moka/future/struct.Cache.html)
 pub type MokaCache<K, V> = moka::future::Cache<K, V>;
@@ -50,8 +41,8 @@ pub type MokaCacheBuilder<K, V> = moka::future::CacheBuilder<K, V, MokaCache<K,
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct MokaBuilder {
-    config: MokaConfig,
-    builder: MokaCacheBuilder<String, MokaValue>,
+    pub(super) config: MokaConfig,
+    pub(super) builder: MokaCacheBuilder<String, MokaValue>,
 }
 
 impl Debug for MokaBuilder {
diff --git a/core/src/services/moka/config.rs b/core/src/services/moka/config.rs
index 69641d482..4d8d9c0f7 100644
--- a/core/src/services/moka/config.rs
+++ b/core/src/services/moka/config.rs
@@ -21,6 +21,7 @@ use std::time::Duration;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::MokaBuilder;
 
 /// Config for Moka services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -57,3 +58,14 @@ impl Debug for MokaConfig {
             .finish_non_exhaustive()
     }
 }
+
+impl crate::Configurator for MokaConfig {
+    type Builder = MokaBuilder;
+    fn into_builder(self) -> Self::Builder {
+        MokaBuilder {
+            config: self,
+            ..Default::default()
+        }
+    }
+}
+
diff --git a/core/src/services/mongodb/backend.rs b/core/src/services/mongodb/backend.rs
index 37a237041..1cb9e8511 100644
--- a/core/src/services/mongodb/backend.rs
+++ b/core/src/services/mongodb/backend.rs
@@ -29,17 +29,10 @@ use crate::raw::*;
 use crate::services::MongodbConfig;
 use crate::*;
 
-impl Configurator for MongodbConfig {
-    type Builder = MongodbBuilder;
-    fn into_builder(self) -> Self::Builder {
-        MongodbBuilder { config: self }
-    }
-}
-
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct MongodbBuilder {
-    config: MongodbConfig,
+    pub(super) config: MongodbConfig,
 }
 
 impl Debug for MongodbBuilder {
diff --git a/core/src/services/mongodb/config.rs b/core/src/services/mongodb/config.rs
index 4001533f2..284dc48ba 100644
--- a/core/src/services/mongodb/config.rs
+++ b/core/src/services/mongodb/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::MongodbBuilder;
 
 /// Config for Mongodb service support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -52,3 +53,11 @@ impl Debug for MongodbConfig {
             .finish()
     }
 }
+
+impl crate::Configurator for MongodbConfig {
+    type Builder = MongodbBuilder;
+    fn into_builder(self) -> Self::Builder {
+        MongodbBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/monoiofs/backend.rs b/core/src/services/monoiofs/backend.rs
index 9332b247e..a842d58b9 100644
--- a/core/src/services/monoiofs/backend.rs
+++ b/core/src/services/monoiofs/backend.rs
@@ -30,18 +30,11 @@ use crate::raw::*;
 use crate::services::MonoiofsConfig;
 use crate::*;
 
-impl Configurator for MonoiofsConfig {
-    type Builder = MonoiofsBuilder;
-    fn into_builder(self) -> Self::Builder {
-        MonoiofsBuilder { config: self }
-    }
-}
-
 /// File system support via [`monoio`].
 #[doc = include_str!("docs.md")]
 #[derive(Default, Debug)]
 pub struct MonoiofsBuilder {
-    config: MonoiofsConfig,
+    pub(super) config: MonoiofsConfig,
 }
 
 impl MonoiofsBuilder {
diff --git a/core/src/services/monoiofs/config.rs b/core/src/services/monoiofs/config.rs
index 09854e7f5..f50243637 100644
--- a/core/src/services/monoiofs/config.rs
+++ b/core/src/services/monoiofs/config.rs
@@ -19,6 +19,7 @@ use std::fmt::Debug;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::MonoiofsBuilder;
 
 /// Config for monoiofs services support.
 #[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -32,3 +33,11 @@ pub struct MonoiofsConfig {
     /// Builder::build will return error if not set.
     pub root: Option<String>,
 }
+
+impl crate::Configurator for MonoiofsConfig {
+    type Builder = MonoiofsBuilder;
+    fn into_builder(self) -> Self::Builder {
+        MonoiofsBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/mysql/backend.rs b/core/src/services/mysql/backend.rs
index 04dcceeca..54695164b 100644
--- a/core/src/services/mysql/backend.rs
+++ b/core/src/services/mysql/backend.rs
@@ -27,17 +27,10 @@ use crate::raw::*;
 use crate::services::MysqlConfig;
 use crate::*;
 
-impl Configurator for MysqlConfig {
-    type Builder = MysqlBuilder;
-    fn into_builder(self) -> Self::Builder {
-        MysqlBuilder { config: self }
-    }
-}
-
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct MysqlBuilder {
-    config: MysqlConfig,
+    pub(super) config: MysqlConfig,
 }
 
 impl Debug for MysqlBuilder {
diff --git a/core/src/services/mysql/config.rs b/core/src/services/mysql/config.rs
index 71754ce2e..465edd7cf 100644
--- a/core/src/services/mysql/config.rs
+++ b/core/src/services/mysql/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::MysqlBuilder;
 
 /// Config for Mysql services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -64,3 +65,11 @@ impl Debug for MysqlConfig {
             .finish()
     }
 }
+
+impl crate::Configurator for MysqlConfig {
+    type Builder = MysqlBuilder;
+    fn into_builder(self) -> Self::Builder {
+        MysqlBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/obs/backend.rs b/core/src/services/obs/backend.rs
index 71d49ceaa..3b1e966fe 100644
--- a/core/src/services/obs/backend.rs
+++ b/core/src/services/obs/backend.rs
@@ -38,43 +38,16 @@ use super::writer::ObsWriter;
 use super::writer::ObsWriters;
 use crate::raw::*;
 use crate::services::ObsConfig;
-use crate::types::OperatorUri;
 use crate::*;
-impl Configurator for ObsConfig {
-    type Builder = ObsBuilder;
-
-    fn from_uri(uri: &OperatorUri) -> Result<Self> {
-        let mut map = uri.options().clone();
-
-        if let Some(name) = uri.name() {
-            map.insert("bucket".to_string(), name.to_string());
-        }
-
-        if let Some(root) = uri.root() {
-            map.insert("root".to_string(), root.to_string());
-        }
-
-        Self::from_iter(map)
-    }
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        ObsBuilder {
-            config: self,
-
-            http_client: None,
-        }
-    }
-}
 
 /// Huawei-Cloud Object Storage Service (OBS) support
 #[doc = include_str!("docs.md")]
 #[derive(Default, Clone)]
 pub struct ObsBuilder {
-    config: ObsConfig,
+    pub(super) config: ObsConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for ObsBuilder {
@@ -449,22 +422,3 @@ impl Access for ObsBackend {
         )))
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use crate::Configurator;
-    use crate::types::OperatorUri;
-
-    #[test]
-    fn from_uri_extracts_bucket_and_root() {
-        let uri = OperatorUri::new(
-            "obs://example-bucket/path/to/root".parse().unwrap(),
-            Vec::<(String, String)>::new(),
-        )
-        .unwrap();
-        let cfg = ObsConfig::from_uri(&uri).unwrap();
-        assert_eq!(cfg.bucket.as_deref(), Some("example-bucket"));
-        assert_eq!(cfg.root.as_deref(), Some("path/to/root"));
-    }
-}
diff --git a/core/src/services/obs/config.rs b/core/src/services/obs/config.rs
index c92369cbc..6e3e8870c 100644
--- a/core/src/services/obs/config.rs
+++ b/core/src/services/obs/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::ObsBuilder;
 
 /// Config for Huawei-Cloud Object Storage Service (OBS) support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -51,3 +52,49 @@ impl Debug for ObsConfig {
             .finish()
     }
 }
+
+impl crate::Configurator for ObsConfig {
+    type Builder = ObsBuilder;
+
+    fn from_uri(uri: &crate::types::OperatorUri) -> crate::Result<Self> {
+        let mut map = uri.options().clone();
+
+        if let Some(name) = uri.name() {
+            map.insert("bucket".to_string(), name.to_string());
+        }
+
+        if let Some(root) = uri.root() {
+            map.insert("root".to_string(), root.to_string());
+        }
+
+        Self::from_iter(map)
+    }
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        ObsBuilder {
+            config: self,
+
+            http_client: None,
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::Configurator;
+    use crate::types::OperatorUri;
+
+    #[test]
+    fn from_uri_extracts_bucket_and_root() {
+        let uri = OperatorUri::new(
+            "obs://example-bucket/path/to/root".parse().unwrap(),
+            Vec::<(String, String)>::new(),
+        )
+        .unwrap();
+        let cfg = ObsConfig::from_uri(&uri).unwrap();
+        assert_eq!(cfg.bucket.as_deref(), Some("example-bucket"));
+        assert_eq!(cfg.root.as_deref(), Some("path/to/root"));
+    }
+}
diff --git a/core/src/services/onedrive/builder.rs b/core/src/services/onedrive/builder.rs
index 28df66c2c..02528c4a1 100644
--- a/core/src/services/onedrive/builder.rs
+++ b/core/src/services/onedrive/builder.rs
@@ -33,22 +33,13 @@ use crate::raw::Timestamp;
 use crate::raw::normalize_root;
 use crate::services::OnedriveConfig;
 use crate::*;
-impl Configurator for OnedriveConfig {
-    type Builder = OnedriveBuilder;
-    fn into_builder(self) -> Self::Builder {
-        OnedriveBuilder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
 
 /// Microsoft [OneDrive](https://onedrive.com) backend support.
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct OnedriveBuilder {
-    config: OnedriveConfig,
-    http_client: Option<HttpClient>,
+    pub(super) config: OnedriveConfig,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for OnedriveBuilder {
diff --git a/core/src/services/onedrive/config.rs b/core/src/services/onedrive/config.rs
index 22fbb21b8..43f68dbd9 100644
--- a/core/src/services/onedrive/config.rs
+++ b/core/src/services/onedrive/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::builder::OnedriveBuilder;
 
 /// Config for [OneDrive](https://onedrive.com) backend support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -47,3 +48,14 @@ impl Debug for OnedriveConfig {
             .finish_non_exhaustive()
     }
 }
+
+impl crate::Configurator for OnedriveConfig {
+    type Builder = OnedriveBuilder;
+    fn into_builder(self) -> Self::Builder {
+        OnedriveBuilder {
+            config: self,
+            http_client: None,
+        }
+    }
+}
+
diff --git a/core/src/services/oss/backend.rs b/core/src/services/oss/backend.rs
index 0b2856c43..9fab743a3 100644
--- a/core/src/services/oss/backend.rs
+++ b/core/src/services/oss/backend.rs
@@ -38,45 +38,17 @@ use super::writer::OssWriter;
 use super::writer::OssWriters;
 use crate::raw::*;
 use crate::services::OssConfig;
-use crate::types::OperatorUri;
 use crate::*;
 const DEFAULT_BATCH_MAX_OPERATIONS: usize = 1000;
 
-impl Configurator for OssConfig {
-    type Builder = OssBuilder;
-
-    fn from_uri(uri: &OperatorUri) -> Result<Self> {
-        let mut map = uri.options().clone();
-
-        if let Some(name) = uri.name() {
-            map.insert("bucket".to_string(), name.to_string());
-        }
-
-        if let Some(root) = uri.root() {
-            map.insert("root".to_string(), root.to_string());
-        }
-
-        Self::from_iter(map)
-    }
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        OssBuilder {
-            config: self,
-
-            http_client: None,
-        }
-    }
-}
-
 /// Aliyun Object Storage Service (OSS) support
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct OssBuilder {
-    config: OssConfig,
+    pub(super) config: OssConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for OssBuilder {
@@ -747,22 +719,3 @@ impl Access for OssBackend {
         )))
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use crate::Configurator;
-    use crate::types::OperatorUri;
-
-    #[test]
-    fn from_uri_extracts_bucket_and_root() {
-        let uri = OperatorUri::new(
-            "oss://example-bucket/path/to/root".parse().unwrap(),
-            Vec::<(String, String)>::new(),
-        )
-        .unwrap();
-        let cfg = OssConfig::from_uri(&uri).unwrap();
-        assert_eq!(cfg.bucket, "example-bucket");
-        assert_eq!(cfg.root.as_deref(), Some("path/to/root"));
-    }
-}
diff --git a/core/src/services/oss/config.rs b/core/src/services/oss/config.rs
index abbf94d03..c710d73ab 100644
--- a/core/src/services/oss/config.rs
+++ b/core/src/services/oss/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::OssBuilder;
 
 /// Config for Aliyun Object Storage Service (OSS) support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -111,3 +112,49 @@ impl Debug for OssConfig {
         d.finish_non_exhaustive()
     }
 }
+
+impl crate::Configurator for OssConfig {
+    type Builder = OssBuilder;
+
+    fn from_uri(uri: &crate::types::OperatorUri) -> crate::Result<Self> {
+        let mut map = uri.options().clone();
+
+        if let Some(name) = uri.name() {
+            map.insert("bucket".to_string(), name.to_string());
+        }
+
+        if let Some(root) = uri.root() {
+            map.insert("root".to_string(), root.to_string());
+        }
+
+        Self::from_iter(map)
+    }
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        OssBuilder {
+            config: self,
+
+            http_client: None,
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::Configurator;
+    use crate::types::OperatorUri;
+
+    #[test]
+    fn from_uri_extracts_bucket_and_root() {
+        let uri = OperatorUri::new(
+            "oss://example-bucket/path/to/root".parse().unwrap(),
+            Vec::<(String, String)>::new(),
+        )
+        .unwrap();
+        let cfg = OssConfig::from_uri(&uri).unwrap();
+        assert_eq!(cfg.bucket, "example-bucket");
+        assert_eq!(cfg.root.as_deref(), Some("path/to/root"));
+    }
+}
diff --git a/core/src/services/pcloud/backend.rs b/core/src/services/pcloud/backend.rs
index 38bc2ef81..81c711441 100644
--- a/core/src/services/pcloud/backend.rs
+++ b/core/src/services/pcloud/backend.rs
@@ -35,26 +35,15 @@ use super::writer::PcloudWriters;
 use crate::raw::*;
 use crate::services::PcloudConfig;
 use crate::*;
-impl Configurator for PcloudConfig {
-    type Builder = PcloudBuilder;
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        PcloudBuilder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
 
 /// [pCloud](https://www.pcloud.com/) services support.
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct PcloudBuilder {
-    config: PcloudConfig,
+    pub(super) config: PcloudConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for PcloudBuilder {
diff --git a/core/src/services/pcloud/config.rs b/core/src/services/pcloud/config.rs
index 3d5d39278..a96f34e5e 100644
--- a/core/src/services/pcloud/config.rs
+++ b/core/src/services/pcloud/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::PcloudBuilder;
 
 /// Config for Pcloud services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -49,3 +50,16 @@ impl Debug for PcloudConfig {
         ds.finish()
     }
 }
+
+impl crate::Configurator for PcloudConfig {
+    type Builder = PcloudBuilder;
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        PcloudBuilder {
+            config: self,
+            http_client: None,
+        }
+    }
+}
+
diff --git a/core/src/services/persy/backend.rs b/core/src/services/persy/backend.rs
index 7fefeff65..a55e17e93 100644
--- a/core/src/services/persy/backend.rs
+++ b/core/src/services/persy/backend.rs
@@ -30,18 +30,11 @@ use crate::raw::*;
 use crate::services::PersyConfig;
 use crate::*;
 
-impl Configurator for PersyConfig {
-    type Builder = PersyBuilder;
-    fn into_builder(self) -> Self::Builder {
-        PersyBuilder { config: self }
-    }
-}
-
 /// persy service support.
 #[doc = include_str!("docs.md")]
 #[derive(Default, Debug)]
 pub struct PersyBuilder {
-    config: PersyConfig,
+    pub(super) config: PersyConfig,
 }
 
 impl PersyBuilder {
diff --git a/core/src/services/persy/config.rs b/core/src/services/persy/config.rs
index 23c5c7ea2..4e458ba32 100644
--- a/core/src/services/persy/config.rs
+++ b/core/src/services/persy/config.rs
@@ -17,6 +17,7 @@
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::PersyBuilder;
 
 /// Config for persy service support.
 #[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -30,3 +31,11 @@ pub struct PersyConfig {
     /// That name of the persy index.
     pub index: Option<String>,
 }
+
+impl crate::Configurator for PersyConfig {
+    type Builder = PersyBuilder;
+    fn into_builder(self) -> Self::Builder {
+        PersyBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/postgresql/backend.rs b/core/src/services/postgresql/backend.rs
index 2d82b61cf..8d5332d84 100644
--- a/core/src/services/postgresql/backend.rs
+++ b/core/src/services/postgresql/backend.rs
@@ -28,18 +28,11 @@ use crate::raw::*;
 use crate::services::PostgresqlConfig;
 use crate::*;
 
-impl Configurator for PostgresqlConfig {
-    type Builder = PostgresqlBuilder;
-    fn into_builder(self) -> Self::Builder {
-        PostgresqlBuilder { config: self }
-    }
-}
-
 /// [PostgreSQL](https://www.postgresql.org/) services support.
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct PostgresqlBuilder {
-    config: PostgresqlConfig,
+    pub(super) config: PostgresqlConfig,
 }
 
 impl Debug for PostgresqlBuilder {
diff --git a/core/src/services/postgresql/config.rs b/core/src/services/postgresql/config.rs
index 6b2d4775a..1cebe613f 100644
--- a/core/src/services/postgresql/config.rs
+++ b/core/src/services/postgresql/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::PostgresqlBuilder;
 
 /// Config for PostgreSQL services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -64,3 +65,11 @@ impl Debug for PostgresqlConfig {
             .finish()
     }
 }
+
+impl crate::Configurator for PostgresqlConfig {
+    type Builder = PostgresqlBuilder;
+    fn into_builder(self) -> Self::Builder {
+        PostgresqlBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/redb/backend.rs b/core/src/services/redb/backend.rs
index e2fcf07c1..88a291fb2 100644
--- a/core/src/services/redb/backend.rs
+++ b/core/src/services/redb/backend.rs
@@ -28,23 +28,13 @@ use crate::raw::*;
 use crate::services::RedbConfig;
 use crate::*;
 
-impl Configurator for RedbConfig {
-    type Builder = RedbBuilder;
-    fn into_builder(self) -> Self::Builder {
-        RedbBuilder {
-            config: self,
-            database: None,
-        }
-    }
-}
-
 /// Redb service support.
 #[doc = include_str!("docs.md")]
 #[derive(Default, Debug)]
 pub struct RedbBuilder {
-    config: RedbConfig,
+    pub(super) config: RedbConfig,
 
-    database: Option<Arc<redb::Database>>,
+    pub(super) database: Option<Arc<redb::Database>>,
 }
 
 impl RedbBuilder {
diff --git a/core/src/services/redb/config.rs b/core/src/services/redb/config.rs
index 3a5283873..bfbfa6a8f 100644
--- a/core/src/services/redb/config.rs
+++ b/core/src/services/redb/config.rs
@@ -19,6 +19,7 @@ use std::fmt::Debug;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::RedbBuilder;
 
 /// Config for redb service support.
 #[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -32,3 +33,14 @@ pub struct RedbConfig {
     /// The table name for redb.
     pub table: Option<String>,
 }
+
+impl crate::Configurator for RedbConfig {
+    type Builder = RedbBuilder;
+    fn into_builder(self) -> Self::Builder {
+        RedbBuilder {
+            config: self,
+            database: None,
+        }
+    }
+}
+
diff --git a/core/src/services/redis/backend.rs b/core/src/services/redis/backend.rs
index 3731aa59a..f85e08f5f 100644
--- a/core/src/services/redis/backend.rs
+++ b/core/src/services/redis/backend.rs
@@ -40,18 +40,11 @@ use crate::*;
 const DEFAULT_REDIS_ENDPOINT: &str = "tcp://127.0.0.1:6379";
 const DEFAULT_REDIS_PORT: u16 = 6379;
 
-impl Configurator for RedisConfig {
-    type Builder = RedisBuilder;
-    fn into_builder(self) -> Self::Builder {
-        RedisBuilder { config: self }
-    }
-}
-
 /// [Redis](https://redis.io/) services support.
 #[doc = include_str!("docs.md")]
 #[derive(Clone, Default)]
 pub struct RedisBuilder {
-    config: RedisConfig,
+    pub(super) config: RedisConfig,
 }
 
 impl Debug for RedisBuilder {
@@ -375,68 +368,3 @@ impl Access for RedisAccessor {
         Ok((RpList::default(), ()))
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use std::time::Duration;
-
-    #[test]
-    fn test_redis_accessor_creation() {
-        let core = RedisCore {
-            addr: "redis://127.0.0.1:6379".to_string(),
-            client: None,
-            cluster_client: None,
-            conn: OnceCell::new(),
-            default_ttl: Some(Duration::from_secs(60)),
-        };
-
-        let accessor = RedisAccessor::new(core);
-
-        // Verify basic properties
-        assert_eq!(accessor.root, "/");
-        assert_eq!(accessor.info.scheme(), "redis");
-        assert!(accessor.info.native_capability().read);
-        assert!(accessor.info.native_capability().write);
-        assert!(accessor.info.native_capability().delete);
-        assert!(accessor.info.native_capability().stat);
-    }
-
-    #[test]
-    fn test_redis_accessor_with_root() {
-        let core = RedisCore {
-            addr: "redis://127.0.0.1:6379".to_string(),
-            client: None,
-            cluster_client: None,
-            conn: OnceCell::new(),
-            default_ttl: None,
-        };
-
-        let accessor = RedisAccessor::new(core).with_normalized_root("/test/".to_string());
-
-        assert_eq!(accessor.root, "/test/");
-        assert_eq!(accessor.info.root(), "/test/".into());
-    }
-
-    #[test]
-    fn test_redis_builder_interface() {
-        // Test that RedisBuilder still works with the new implementation
-        let builder = RedisBuilder::default()
-            .endpoint("redis://localhost:6379")
-            .username("testuser")
-            .password("testpass")
-            .db(1)
-            .root("/test");
-
-        // The builder should be able to create configuration
-        assert!(builder.config.endpoint.is_some());
-        assert_eq!(
-            builder.config.endpoint.as_ref().unwrap(),
-            "redis://localhost:6379"
-        );
-        assert_eq!(builder.config.username.as_ref().unwrap(), "testuser");
-        assert_eq!(builder.config.password.as_ref().unwrap(), "testpass");
-        assert_eq!(builder.config.db, 1);
-        assert_eq!(builder.config.root.as_ref().unwrap(), "/test");
-    }
-}
diff --git a/core/src/services/redis/config.rs b/core/src/services/redis/config.rs
index c16a56472..3b08cec2f 100644
--- a/core/src/services/redis/config.rs
+++ b/core/src/services/redis/config.rs
@@ -21,6 +21,7 @@ use std::time::Duration;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::RedisBuilder;
 
 /// Config for Redis services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -77,3 +78,37 @@ impl Debug for RedisConfig {
         d.finish_non_exhaustive()
     }
 }
+
+impl crate::Configurator for RedisConfig {
+    type Builder = RedisBuilder;
+    fn into_builder(self) -> Self::Builder {
+        RedisBuilder { config: self }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_redis_builder_interface() {
+        // Test that RedisBuilder still works with the new implementation
+        let builder = RedisBuilder::default()
+            .endpoint("redis://localhost:6379")
+            .username("testuser")
+            .password("testpass")
+            .db(1)
+            .root("/test");
+
+        // The builder should be able to create configuration
+        assert!(builder.config.endpoint.is_some());
+        assert_eq!(
+            builder.config.endpoint.as_ref().unwrap(),
+            "redis://localhost:6379"
+        );
+        assert_eq!(builder.config.username.as_ref().unwrap(), "testuser");
+        assert_eq!(builder.config.password.as_ref().unwrap(), "testpass");
+        assert_eq!(builder.config.db, 1);
+        assert_eq!(builder.config.root.as_ref().unwrap(), "/test");
+    }
+}
diff --git a/core/src/services/rocksdb/backend.rs b/core/src/services/rocksdb/backend.rs
index 26d5df375..624d2abe6 100644
--- a/core/src/services/rocksdb/backend.rs
+++ b/core/src/services/rocksdb/backend.rs
@@ -27,18 +27,11 @@ use crate::raw::*;
 use crate::services::RocksdbConfig;
 use crate::*;
 
-impl Configurator for RocksdbConfig {
-    type Builder = RocksdbBuilder;
-    fn into_builder(self) -> Self::Builder {
-        RocksdbBuilder { config: self }
-    }
-}
-
 /// RocksDB service support.
 #[doc = include_str!("docs.md")]
 #[derive(Clone, Default)]
 pub struct RocksdbBuilder {
-    config: RocksdbConfig,
+    pub(super) config: RocksdbConfig,
 }
 
 impl RocksdbBuilder {
diff --git a/core/src/services/rocksdb/config.rs b/core/src/services/rocksdb/config.rs
index a69e497a1..ce81d48ee 100644
--- a/core/src/services/rocksdb/config.rs
+++ b/core/src/services/rocksdb/config.rs
@@ -19,6 +19,7 @@ use std::fmt::Debug;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::RocksdbBuilder;
 
 /// Config for Rocksdb Service.
 #[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -32,3 +33,11 @@ pub struct RocksdbConfig {
     /// default is "/"
     pub root: Option<String>,
 }
+
+impl crate::Configurator for RocksdbConfig {
+    type Builder = RocksdbBuilder;
+    fn into_builder(self) -> Self::Builder {
+        RocksdbBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/s3/backend.rs b/core/src/services/s3/backend.rs
index 309859dab..e772a5642 100644
--- a/core/src/services/s3/backend.rs
+++ b/core/src/services/s3/backend.rs
@@ -54,7 +54,6 @@ use super::writer::S3Writers;
 use crate::raw::oio::PageLister;
 use crate::raw::*;
 use crate::services::S3Config;
-use crate::types::OperatorUri;
 use crate::*;
 
 /// Allow constructing correct region endpoint if user gives a global endpoint.
@@ -70,46 +69,18 @@ static ENDPOINT_TEMPLATES: LazyLock<HashMap<&'static str, &'static str>> = LazyL
 
 const DEFAULT_BATCH_MAX_OPERATIONS: usize = 1000;
 
-impl Configurator for S3Config {
-    type Builder = S3Builder;
-
-    fn from_uri(uri: &OperatorUri) -> Result<Self> {
-        let mut map = uri.options().clone();
-
-        if let Some(name) = uri.name() {
-            map.insert("bucket".to_string(), name.to_string());
-        }
-
-        if let Some(root) = uri.root() {
-            map.insert("root".to_string(), root.to_string());
-        }
-
-        Self::from_iter(map)
-    }
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        S3Builder {
-            config: self,
-            customized_credential_load: None,
-
-            http_client: None,
-        }
-    }
-}
-
 /// Aws S3 and compatible services (including minio, digitalocean space, Tencent Cloud Object Storage(COS) and so on) support.
 /// For more information about s3-compatible services, refer to [Compatible Services](#compatible-services).
 #[doc = include_str!("docs.md")]
 #[doc = include_str!("compatible_services.md")]
 #[derive(Default)]
 pub struct S3Builder {
-    config: S3Config,
+    pub(super) config: S3Config,
 
-    customized_credential_load: Option<Box<dyn AwsCredentialLoad>>,
+    pub(super) customized_credential_load: Option<Box<dyn AwsCredentialLoad>>,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for S3Builder {
@@ -1173,124 +1144,3 @@ impl Access for S3Backend {
         )))
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use crate::Configurator;
-    use crate::types::OperatorUri;
-
-    #[test]
-    fn test_is_valid_bucket() {
-        let bucket_cases = vec![
-            ("", false, false),
-            ("test", false, true),
-            ("test.xyz", false, true),
-            ("", true, false),
-            ("test", true, true),
-            ("test.xyz", true, false),
-        ];
-
-        for (bucket, enable_virtual_host_style, expected) in bucket_cases {
-            let mut b = S3Builder::default();
-            b = b.bucket(bucket);
-            if enable_virtual_host_style {
-                b = b.enable_virtual_host_style();
-            }
-            assert_eq!(b.is_bucket_valid(), expected)
-        }
-    }
-
-    #[test]
-    fn test_build_endpoint() {
-        let _ = tracing_subscriber::fmt().with_test_writer().try_init();
-
-        let endpoint_cases = vec![
-            Some("s3.amazonaws.com"),
-            Some("https://s3.amazonaws.com"),
-            Some("https://s3.us-east-2.amazonaws.com"),
-            None,
-        ];
-
-        for endpoint in &endpoint_cases {
-            let mut b = S3Builder::default().bucket("test");
-            if let Some(endpoint) = endpoint {
-                b = b.endpoint(endpoint);
-            }
-
-            let endpoint = b.build_endpoint("us-east-2");
-            assert_eq!(endpoint, "https://s3.us-east-2.amazonaws.com/test");
-        }
-
-        for endpoint in &endpoint_cases {
-            let mut b = S3Builder::default()
-                .bucket("test")
-                .enable_virtual_host_style();
-            if let Some(endpoint) = endpoint {
-                b = b.endpoint(endpoint);
-            }
-
-            let endpoint = b.build_endpoint("us-east-2");
-            assert_eq!(endpoint, "https://test.s3.us-east-2.amazonaws.com");
-        }
-    }
-
-    #[tokio::test]
-    async fn test_detect_region() {
-        let cases = vec![
-            (
-                "aws s3 without region in endpoint",
-                "https://s3.amazonaws.com",
-                "example",
-                Some("us-east-1"),
-            ),
-            (
-                "aws s3 with region in endpoint",
-                "https://s3.us-east-1.amazonaws.com",
-                "example",
-                Some("us-east-1"),
-            ),
-            (
-                "oss with public endpoint",
-                "https://oss-ap-southeast-1.aliyuncs.com",
-                "example",
-                Some("oss-ap-southeast-1"),
-            ),
-            (
-                "oss with internal endpoint",
-                "https://oss-cn-hangzhou-internal.aliyuncs.com",
-                "example",
-                Some("oss-cn-hangzhou-internal"),
-            ),
-            (
-                "r2",
-                "https://abc.xxxxx.r2.cloudflarestorage.com",
-                "example",
-                Some("auto"),
-            ),
-            (
-                "invalid service",
-                "https://opendal.apache.org",
-                "example",
-                None,
-            ),
-        ];
-
-        for (name, endpoint, bucket, expected) in cases {
-            let region = S3Builder::detect_region(endpoint, bucket).await;
-            assert_eq!(region.as_deref(), expected, "{name}");
-        }
-    }
-
-    #[test]
-    fn from_uri_extracts_bucket_and_root() {
-        let uri = OperatorUri::new(
-            "s3://example-bucket/path/to/root".parse().unwrap(),
-            Vec::<(String, String)>::new(),
-        )
-        .unwrap();
-        let cfg = S3Config::from_uri(&uri).unwrap();
-        assert_eq!(cfg.bucket, "example-bucket");
-        assert_eq!(cfg.root.as_deref(), Some("path/to/root"));
-    }
-}
diff --git a/core/src/services/s3/config.rs b/core/src/services/s3/config.rs
index 0b371db2d..7eff496ac 100644
--- a/core/src/services/s3/config.rs
+++ b/core/src/services/s3/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::S3Builder;
 
 /// Config for Aws S3 and compatible services (including minio, digitalocean space, Tencent Cloud Object Storage(COS) and so on) support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -230,9 +231,41 @@ impl Debug for S3Config {
     }
 }
 
+
+
+impl crate::Configurator for S3Config {
+    type Builder = S3Builder;
+
+    fn from_uri(uri: &crate::types::OperatorUri) -> crate::Result<Self> {
+        let mut map = uri.options().clone();
+
+        if let Some(name) = uri.name() {
+            map.insert("bucket".to_string(), name.to_string());
+        }
+
+        if let Some(root) = uri.root() {
+            map.insert("root".to_string(), root.to_string());
+        }
+
+        Self::from_iter(map)
+    }
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        S3Builder {
+            config: self,
+            customized_credential_load: None,
+
+            http_client: None,
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
+    use crate::Configurator;
+    use crate::types::OperatorUri;
 
     #[test]
     fn test_s3_config_original_field_names() {
@@ -324,4 +357,16 @@ mod tests {
             Some("dGVzdC1jdXN0b21lci1rZXk=".to_string())
         );
     }
+
+    #[test]
+    fn from_uri_extracts_bucket_and_root() {
+        let uri = OperatorUri::new(
+            "s3://example-bucket/path/to/root".parse().unwrap(),
+            Vec::<(String, String)>::new(),
+        )
+        .unwrap();
+        let cfg = S3Config::from_uri(&uri).unwrap();
+        assert_eq!(cfg.bucket, "example-bucket");
+        assert_eq!(cfg.root.as_deref(), Some("path/to/root"));
+    }
 }
diff --git a/core/src/services/seafile/backend.rs b/core/src/services/seafile/backend.rs
index 3d88ac808..a476a6c7b 100644
--- a/core/src/services/seafile/backend.rs
+++ b/core/src/services/seafile/backend.rs
@@ -37,26 +37,15 @@ use super::writer::SeafileWriters;
 use crate::raw::*;
 use crate::services::SeafileConfig;
 use crate::*;
-impl Configurator for SeafileConfig {
-    type Builder = SeafileBuilder;
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        SeafileBuilder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
 
 /// [seafile](https://www.seafile.com) services support.
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct SeafileBuilder {
-    config: SeafileConfig,
+    pub(super) config: SeafileConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for SeafileBuilder {
diff --git a/core/src/services/seafile/config.rs b/core/src/services/seafile/config.rs
index ef1450661..eafec0ec2 100644
--- a/core/src/services/seafile/config.rs
+++ b/core/src/services/seafile/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::SeafileBuilder;
 
 /// Config for seafile services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -54,3 +55,16 @@ impl Debug for SeafileConfig {
         d.finish_non_exhaustive()
     }
 }
+
+impl crate::Configurator for SeafileConfig {
+    type Builder = SeafileBuilder;
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        SeafileBuilder {
+            config: self,
+            http_client: None,
+        }
+    }
+}
+
diff --git a/core/src/services/sftp/backend.rs b/core/src/services/sftp/backend.rs
index 8b7f49541..bffb5dc5a 100644
--- a/core/src/services/sftp/backend.rs
+++ b/core/src/services/sftp/backend.rs
@@ -38,31 +38,7 @@ use super::reader::SftpReader;
 use super::writer::SftpWriter;
 use crate::raw::*;
 use crate::services::SftpConfig;
-use crate::types::OperatorUri;
 use crate::*;
-impl Configurator for SftpConfig {
-    type Builder = SftpBuilder;
-
-    fn from_uri(uri: &OperatorUri) -> Result<Self> {
-        let authority = uri.authority().ok_or_else(|| {
-            Error::new(ErrorKind::ConfigInvalid, "uri authority is required")
-                .with_context("service", Scheme::Sftp)
-        })?;
-
-        let mut map = uri.options().clone();
-        map.insert("endpoint".to_string(), authority.to_string());
-
-        if let Some(root) = uri.root() {
-            map.insert("root".to_string(), root.to_string());
-        }
-
-        Self::from_iter(map)
-    }
-
-    fn into_builder(self) -> Self::Builder {
-        SftpBuilder { config: self }
-    }
-}
 
 /// SFTP services support. (only works on unix)
 ///
@@ -76,7 +52,7 @@ impl Configurator for SftpConfig {
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct SftpBuilder {
-    config: SftpConfig,
+    pub(super) config: SftpConfig,
 }
 
 impl Debug for SftpBuilder {
@@ -413,40 +389,3 @@ impl Access for SftpBackend {
         Ok(RpRename::default())
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn from_uri_sets_endpoint_and_root() {
-        let uri = OperatorUri::new(
-            "sftp://sftp.example.com/home/alice".parse().unwrap(),
-            Vec::<(String, String)>::new(),
-        )
-        .unwrap();
-
-        let cfg = SftpConfig::from_uri(&uri).unwrap();
-        assert_eq!(cfg.endpoint.as_deref(), Some("sftp.example.com"));
-        assert_eq!(cfg.root.as_deref(), Some("home/alice"));
-    }
-
-    #[test]
-    fn from_uri_applies_connection_overrides() {
-        let uri = OperatorUri::new(
-            "sftp://host".parse().unwrap(),
-            vec![
-                ("user".to_string(), "alice".to_string()),
-                ("key".to_string(), "/home/alice/.ssh/id_rsa".to_string()),
-                ("known_hosts_strategy".to_string(), "accept".to_string()),
-            ],
-        )
-        .unwrap();
-
-        let cfg = SftpConfig::from_uri(&uri).unwrap();
-        assert_eq!(cfg.endpoint.as_deref(), Some("host"));
-        assert_eq!(cfg.user.as_deref(), Some("alice"));
-        assert_eq!(cfg.key.as_deref(), Some("/home/alice/.ssh/id_rsa"));
-        assert_eq!(cfg.known_hosts_strategy.as_deref(), Some("accept"));
-    }
-}
diff --git a/core/src/services/sftp/config.rs b/core/src/services/sftp/config.rs
index c84a6a9fa..c67fd0bdb 100644
--- a/core/src/services/sftp/config.rs
+++ b/core/src/services/sftp/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::SftpBuilder;
 
 /// Config for Sftp Service support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -48,3 +49,66 @@ impl Debug for SftpConfig {
             .finish_non_exhaustive()
     }
 }
+
+impl crate::Configurator for SftpConfig {
+    type Builder = SftpBuilder;
+
+    fn from_uri(uri: &crate::types::OperatorUri) -> crate::Result<Self> {
+        let authority = uri.authority().ok_or_else(|| {
+            crate::Error::new(crate::ErrorKind::ConfigInvalid, "uri authority is required")
+                .with_context("service", crate::Scheme::Sftp)
+        })?;
+
+        let mut map = uri.options().clone();
+        map.insert("endpoint".to_string(), authority.to_string());
+
+        if let Some(root) = uri.root() {
+            map.insert("root".to_string(), root.to_string());
+        }
+
+        Self::from_iter(map)
+    }
+
+    fn into_builder(self) -> Self::Builder {
+        SftpBuilder { config: self }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::Configurator;
+    use crate::types::OperatorUri;
+
+    #[test]
+    fn from_uri_sets_endpoint_and_root() {
+        let uri = OperatorUri::new(
+            "sftp://sftp.example.com/home/alice".parse().unwrap(),
+            Vec::<(String, String)>::new(),
+        )
+        .unwrap();
+
+        let cfg = SftpConfig::from_uri(&uri).unwrap();
+        assert_eq!(cfg.endpoint.as_deref(), Some("sftp.example.com"));
+        assert_eq!(cfg.root.as_deref(), Some("home/alice"));
+    }
+
+    #[test]
+    fn from_uri_applies_connection_overrides() {
+        let uri = OperatorUri::new(
+            "sftp://host".parse().unwrap(),
+            vec![
+                ("user".to_string(), "alice".to_string()),
+                ("key".to_string(), "/home/alice/.ssh/id_rsa".to_string()),
+                ("known_hosts_strategy".to_string(), "accept".to_string()),
+            ],
+        )
+        .unwrap();
+
+        let cfg = SftpConfig::from_uri(&uri).unwrap();
+        assert_eq!(cfg.endpoint.as_deref(), Some("host"));
+        assert_eq!(cfg.user.as_deref(), Some("alice"));
+        assert_eq!(cfg.key.as_deref(), Some("/home/alice/.ssh/id_rsa"));
+        assert_eq!(cfg.known_hosts_strategy.as_deref(), Some("accept"));
+    }
+}
diff --git a/core/src/services/sled/backend.rs b/core/src/services/sled/backend.rs
index 07b752789..a85ff8d7e 100644
--- a/core/src/services/sled/backend.rs
+++ b/core/src/services/sled/backend.rs
@@ -31,18 +31,11 @@ use crate::*;
 // https://github.com/spacejam/sled/blob/69294e59c718289ab3cb6bd03ac3b9e1e072a1e7/src/db.rs#L5
 const DEFAULT_TREE_ID: &str = r#"__sled__default"#;
 
-impl Configurator for SledConfig {
-    type Builder = SledBuilder;
-    fn into_builder(self) -> Self::Builder {
-        SledBuilder { config: self }
-    }
-}
-
 /// Sled services support.
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct SledBuilder {
-    config: SledConfig,
+    pub(super) config: SledConfig,
 }
 
 impl Debug for SledBuilder {
diff --git a/core/src/services/sled/config.rs b/core/src/services/sled/config.rs
index 740ebb42a..28f3456ad 100644
--- a/core/src/services/sled/config.rs
+++ b/core/src/services/sled/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::SledBuilder;
 
 /// Config for Sled services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -43,3 +44,11 @@ impl Debug for SledConfig {
             .finish()
     }
 }
+
+impl crate::Configurator for SledConfig {
+    type Builder = SledBuilder;
+    fn into_builder(self) -> Self::Builder {
+        SledBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/sqlite/backend.rs b/core/src/services/sqlite/backend.rs
index 7b42bdc64..2129a93ae 100644
--- a/core/src/services/sqlite/backend.rs
+++ b/core/src/services/sqlite/backend.rs
@@ -35,17 +35,10 @@ use crate::raw::*;
 use crate::services::SqliteConfig;
 use crate::*;
 
-impl Configurator for SqliteConfig {
-    type Builder = SqliteBuilder;
-    fn into_builder(self) -> Self::Builder {
-        SqliteBuilder { config: self }
-    }
-}
-
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct SqliteBuilder {
-    config: SqliteConfig,
+    pub(super) config: SqliteConfig,
 }
 
 impl Debug for SqliteBuilder {
diff --git a/core/src/services/sqlite/config.rs b/core/src/services/sqlite/config.rs
index 869e3e0cd..eeee0eee0 100644
--- a/core/src/services/sqlite/config.rs
+++ b/core/src/services/sqlite/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::SqliteBuilder;
 
 /// Config for Sqlite support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -68,3 +69,11 @@ impl Debug for SqliteConfig {
         d.finish_non_exhaustive()
     }
 }
+
+impl crate::Configurator for SqliteConfig {
+    type Builder = SqliteBuilder;
+    fn into_builder(self) -> Self::Builder {
+        SqliteBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/surrealdb/backend.rs b/core/src/services/surrealdb/backend.rs
index 2633d79fd..c80a48c2b 100644
--- a/core/src/services/surrealdb/backend.rs
+++ b/core/src/services/surrealdb/backend.rs
@@ -30,17 +30,10 @@ use crate::raw::normalize_root;
 use crate::services::SurrealdbConfig;
 use crate::*;
 
-impl Configurator for SurrealdbConfig {
-    type Builder = SurrealdbBuilder;
-    fn into_builder(self) -> Self::Builder {
-        SurrealdbBuilder { config: self }
-    }
-}
-
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct SurrealdbBuilder {
-    config: SurrealdbConfig,
+    pub(super) config: SurrealdbConfig,
 }
 
 impl Debug for SurrealdbBuilder {
diff --git a/core/src/services/surrealdb/config.rs b/core/src/services/surrealdb/config.rs
index 112e0bfee..a1ac0f989 100644
--- a/core/src/services/surrealdb/config.rs
+++ b/core/src/services/surrealdb/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::SurrealdbBuilder;
 
 /// Config for Surrealdb services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -62,3 +63,11 @@ impl Debug for SurrealdbConfig {
             .finish()
     }
 }
+
+impl crate::Configurator for SurrealdbConfig {
+    type Builder = SurrealdbBuilder;
+    fn into_builder(self) -> Self::Builder {
+        SurrealdbBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/swift/backend.rs b/core/src/services/swift/backend.rs
index 8a6b64918..0a8b3069d 100644
--- a/core/src/services/swift/backend.rs
+++ b/core/src/services/swift/backend.rs
@@ -32,12 +32,6 @@ use super::writer::SwiftWriter;
 use crate::raw::*;
 use crate::services::SwiftConfig;
 use crate::*;
-impl Configurator for SwiftConfig {
-    type Builder = SwiftBuilder;
-    fn into_builder(self) -> Self::Builder {
-        SwiftBuilder { config: self }
-    }
-}
 
 /// [OpenStack Swift](https://docs.openstack.org/api-ref/object-store/#)'s REST API support.
 /// For more information about swift-compatible services, refer to [Compatible Services](#compatible-services).
@@ -45,7 +39,7 @@ impl Configurator for SwiftConfig {
 #[doc = include_str!("compatible_services.md")]
 #[derive(Default, Clone)]
 pub struct SwiftBuilder {
-    config: SwiftConfig,
+    pub(super) config: SwiftConfig,
 }
 
 impl Debug for SwiftBuilder {
diff --git a/core/src/services/swift/config.rs b/core/src/services/swift/config.rs
index a95e3a023..dc15831f6 100644
--- a/core/src/services/swift/config.rs
+++ b/core/src/services/swift/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::SwiftBuilder;
 
 /// Config for OpenStack Swift support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -51,3 +52,11 @@ impl Debug for SwiftConfig {
         ds.finish()
     }
 }
+
+impl crate::Configurator for SwiftConfig {
+    type Builder = SwiftBuilder;
+    fn into_builder(self) -> Self::Builder {
+        SwiftBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/tikv/backend.rs b/core/src/services/tikv/backend.rs
index 8661c60f5..e15be8ff3 100644
--- a/core/src/services/tikv/backend.rs
+++ b/core/src/services/tikv/backend.rs
@@ -32,18 +32,11 @@ use crate::raw::adapters::kv;
 use crate::services::TikvConfig;
 use crate::*;
 
-impl Configurator for TikvConfig {
-    type Builder = TikvBuilder;
-    fn into_builder(self) -> Self::Builder {
-        TikvBuilder { config: self }
-    }
-}
-
 /// TiKV backend builder
 #[doc = include_str!("docs.md")]
 #[derive(Clone, Default)]
 pub struct TikvBuilder {
-    config: TikvConfig,
+    pub(super) config: TikvConfig,
 }
 
 impl Debug for TikvBuilder {
diff --git a/core/src/services/tikv/config.rs b/core/src/services/tikv/config.rs
index 0f234db26..1758dd6b2 100644
--- a/core/src/services/tikv/config.rs
+++ b/core/src/services/tikv/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::TikvBuilder;
 
 /// Config for Tikv services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -50,3 +51,11 @@ impl Debug for TikvConfig {
             .finish()
     }
 }
+
+impl crate::Configurator for TikvConfig {
+    type Builder = TikvBuilder;
+    fn into_builder(self) -> Self::Builder {
+        TikvBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/upyun/backend.rs b/core/src/services/upyun/backend.rs
index 412011e49..c3cd42f94 100644
--- a/core/src/services/upyun/backend.rs
+++ b/core/src/services/upyun/backend.rs
@@ -32,42 +32,16 @@ use super::writer::UpyunWriter;
 use super::writer::UpyunWriters;
 use crate::raw::*;
 use crate::services::UpyunConfig;
-use crate::types::OperatorUri;
 use crate::*;
-impl Configurator for UpyunConfig {
-    type Builder = UpyunBuilder;
-
-    fn from_uri(uri: &OperatorUri) -> Result<Self> {
-        let mut map = uri.options().clone();
-
-        if let Some(name) = uri.name() {
-            map.insert("bucket".to_string(), name.to_string());
-        }
-
-        if let Some(root) = uri.root() {
-            map.insert("root".to_string(), root.to_string());
-        }
-
-        Self::from_iter(map)
-    }
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        UpyunBuilder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
 
 /// [upyun](https://www.upyun.com/products/file-storage) services support.
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct UpyunBuilder {
-    config: UpyunConfig,
+    pub(super) config: UpyunConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for UpyunBuilder {
@@ -330,22 +304,3 @@ impl Access for UpyunBackend {
         }
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use crate::Configurator;
-    use crate::types::OperatorUri;
-
-    #[test]
-    fn from_uri_extracts_bucket_and_root() {
-        let uri = OperatorUri::new(
-            "upyun://example-bucket/path/to/root".parse().unwrap(),
-            Vec::<(String, String)>::new(),
-        )
-        .unwrap();
-        let cfg = UpyunConfig::from_uri(&uri).unwrap();
-        assert_eq!(cfg.bucket, "example-bucket");
-        assert_eq!(cfg.root.as_deref(), Some("path/to/root"));
-    }
-}
diff --git a/core/src/services/upyun/config.rs b/core/src/services/upyun/config.rs
index 5df98b797..d3490c350 100644
--- a/core/src/services/upyun/config.rs
+++ b/core/src/services/upyun/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::UpyunBuilder;
 
 /// Config for upyun services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -49,3 +50,48 @@ impl Debug for UpyunConfig {
         ds.finish()
     }
 }
+
+impl crate::Configurator for UpyunConfig {
+    type Builder = UpyunBuilder;
+
+    fn from_uri(uri: &crate::types::OperatorUri) -> crate::Result<Self> {
+        let mut map = uri.options().clone();
+
+        if let Some(name) = uri.name() {
+            map.insert("bucket".to_string(), name.to_string());
+        }
+
+        if let Some(root) = uri.root() {
+            map.insert("root".to_string(), root.to_string());
+        }
+
+        Self::from_iter(map)
+    }
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        UpyunBuilder {
+            config: self,
+            http_client: None,
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::Configurator;
+    use crate::types::OperatorUri;
+
+    #[test]
+    fn from_uri_extracts_bucket_and_root() {
+        let uri = OperatorUri::new(
+            "upyun://example-bucket/path/to/root".parse().unwrap(),
+            Vec::<(String, String)>::new(),
+        )
+        .unwrap();
+        let cfg = UpyunConfig::from_uri(&uri).unwrap();
+        assert_eq!(cfg.bucket, "example-bucket");
+        assert_eq!(cfg.root.as_deref(), Some("path/to/root"));
+    }
+}
diff --git a/core/src/services/vercel_artifacts/builder.rs b/core/src/services/vercel_artifacts/builder.rs
index ce0ab2af9..cfe1a1386 100644
--- a/core/src/services/vercel_artifacts/builder.rs
+++ b/core/src/services/vercel_artifacts/builder.rs
@@ -27,26 +27,15 @@ use crate::raw::AccessorInfo;
 use crate::raw::HttpClient;
 use crate::services::VercelArtifactsConfig;
 use crate::*;
-impl Configurator for VercelArtifactsConfig {
-    type Builder = VercelArtifactsBuilder;
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        VercelArtifactsBuilder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
 
 /// [Vercel Cache](https://vercel.com/docs/concepts/monorepos/remote-caching) backend support.
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct VercelArtifactsBuilder {
-    config: VercelArtifactsConfig,
+    pub(super) config: VercelArtifactsConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for VercelArtifactsBuilder {
diff --git a/core/src/services/vercel_artifacts/config.rs b/core/src/services/vercel_artifacts/config.rs
index 1338ce301..2431ab95b 100644
--- a/core/src/services/vercel_artifacts/config.rs
+++ b/core/src/services/vercel_artifacts/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::builder::VercelArtifactsBuilder;
 
 /// Config for Vercel Cache support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -37,3 +38,16 @@ impl Debug for VercelArtifactsConfig {
             .finish()
     }
 }
+
+impl crate::Configurator for VercelArtifactsConfig {
+    type Builder = VercelArtifactsBuilder;
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        VercelArtifactsBuilder {
+            config: self,
+            http_client: None,
+        }
+    }
+}
+
diff --git a/core/src/services/vercel_blob/backend.rs b/core/src/services/vercel_blob/backend.rs
index e6e337dae..a9b403e6f 100644
--- a/core/src/services/vercel_blob/backend.rs
+++ b/core/src/services/vercel_blob/backend.rs
@@ -36,26 +36,15 @@ use super::writer::VercelBlobWriters;
 use crate::raw::*;
 use crate::services::VercelBlobConfig;
 use crate::*;
-impl Configurator for VercelBlobConfig {
-    type Builder = VercelBlobBuilder;
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        VercelBlobBuilder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
 
 /// [VercelBlob](https://vercel.com/docs/storage/vercel-blob) services support.
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct VercelBlobBuilder {
-    config: VercelBlobConfig,
+    pub(super) config: VercelBlobConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for VercelBlobBuilder {
diff --git a/core/src/services/vercel_blob/config.rs b/core/src/services/vercel_blob/config.rs
index 48966f975..f723a71f2 100644
--- a/core/src/services/vercel_blob/config.rs
+++ b/core/src/services/vercel_blob/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::VercelBlobBuilder;
 
 /// Config for VercelBlob services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -43,3 +44,16 @@ impl Debug for VercelBlobConfig {
         ds.finish()
     }
 }
+
+impl crate::Configurator for VercelBlobConfig {
+    type Builder = VercelBlobBuilder;
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        VercelBlobBuilder {
+            config: self,
+            http_client: None,
+        }
+    }
+}
+
diff --git a/core/src/services/webdav/backend.rs b/core/src/services/webdav/backend.rs
index ca64329c7..e8f0ccb11 100644
--- a/core/src/services/webdav/backend.rs
+++ b/core/src/services/webdav/backend.rs
@@ -32,44 +32,16 @@ use super::lister::WebdavLister;
 use super::writer::WebdavWriter;
 use crate::raw::*;
 use crate::services::WebdavConfig;
-use crate::types::OperatorUri;
 use crate::*;
-impl Configurator for WebdavConfig {
-    type Builder = WebdavBuilder;
-
-    fn from_uri(uri: &OperatorUri) -> Result<Self> {
-        let authority = uri.authority().ok_or_else(|| {
-            Error::new(ErrorKind::ConfigInvalid, "uri authority is required")
-                .with_context("service", Scheme::Webdav)
-        })?;
-
-        let mut map = uri.options().clone();
-        map.insert("endpoint".to_string(), format!("https://{authority}"));
-
-        if let Some(root) = uri.root() {
-            map.insert("root".to_string(), root.to_string());
-        }
-
-        Self::from_iter(map)
-    }
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        WebdavBuilder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
 
 /// [WebDAV](https://datatracker.ietf.org/doc/html/rfc4918) backend support.
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct WebdavBuilder {
-    config: WebdavConfig,
+    pub(super) config: WebdavConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for WebdavBuilder {
@@ -333,50 +305,3 @@ impl Access for WebdavBackend {
         }
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn from_uri_sets_endpoint_and_root() {
-        let uri = OperatorUri::new(
-            "webdav://webdav.example.com/remote.php/webdav"
-                .parse()
-                .unwrap(),
-            Vec::<(String, String)>::new(),
-        )
-        .unwrap();
-
-        let cfg = WebdavConfig::from_uri(&uri).unwrap();
-        assert_eq!(cfg.endpoint.as_deref(), Some("https://webdav.example.com"));
-        assert_eq!(cfg.root.as_deref(), Some("remote.php/webdav"));
-    }
-
-    #[test]
-    fn from_uri_ignores_endpoint_override() {
-        let uri = OperatorUri::new(
-            "webdav://dav.internal/data".parse().unwrap(),
-            vec![(
-                "endpoint".to_string(),
-                "http://dav.internal:8080".to_string(),
-            )],
-        )
-        .unwrap();
-
-        let cfg = WebdavConfig::from_uri(&uri).unwrap();
-        assert_eq!(cfg.endpoint.as_deref(), Some("https://dav.internal"));
-    }
-
-    #[test]
-    fn from_uri_propagates_disable_copy() {
-        let uri = OperatorUri::new(
-            "webdav://dav.example.com".parse().unwrap(),
-            vec![("disable_copy".to_string(), "true".to_string())],
-        )
-        .unwrap();
-
-        let cfg = WebdavConfig::from_uri(&uri).unwrap();
-        assert!(cfg.disable_copy);
-    }
-}
diff --git a/core/src/services/webdav/config.rs b/core/src/services/webdav/config.rs
index 364ad5e12..31b817a99 100644
--- a/core/src/services/webdav/config.rs
+++ b/core/src/services/webdav/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::WebdavBuilder;
 
 /// Config for [WebDAV](https://datatracker.ietf.org/doc/html/rfc4918) backend support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -51,3 +52,80 @@ impl Debug for WebdavConfig {
         d.finish_non_exhaustive()
     }
 }
+
+impl crate::Configurator for WebdavConfig {
+    type Builder = WebdavBuilder;
+
+    fn from_uri(uri: &crate::types::OperatorUri) -> crate::Result<Self> {
+        let authority = uri.authority().ok_or_else(|| {
+            crate::Error::new(crate::ErrorKind::ConfigInvalid, "uri authority is required")
+                .with_context("service", crate::Scheme::Webdav)
+        })?;
+
+        let mut map = uri.options().clone();
+        map.insert("endpoint".to_string(), format!("https://{authority}"));
+
+        if let Some(root) = uri.root() {
+            map.insert("root".to_string(), root.to_string());
+        }
+
+        Self::from_iter(map)
+    }
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        WebdavBuilder {
+            config: self,
+            http_client: None,
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::Configurator;
+    use crate::types::OperatorUri;
+
+    #[test]
+    fn from_uri_sets_endpoint_and_root() {
+        let uri = OperatorUri::new(
+            "webdav://webdav.example.com/remote.php/webdav"
+                .parse()
+                .unwrap(),
+            Vec::<(String, String)>::new(),
+        )
+        .unwrap();
+
+        let cfg = WebdavConfig::from_uri(&uri).unwrap();
+        assert_eq!(cfg.endpoint.as_deref(), Some("https://webdav.example.com"));
+        assert_eq!(cfg.root.as_deref(), Some("remote.php/webdav"));
+    }
+
+    #[test]
+    fn from_uri_ignores_endpoint_override() {
+        let uri = OperatorUri::new(
+            "webdav://dav.internal/data".parse().unwrap(),
+            vec![(
+                "endpoint".to_string(),
+                "http://dav.internal:8080".to_string(),
+            )],
+        )
+        .unwrap();
+
+        let cfg = WebdavConfig::from_uri(&uri).unwrap();
+        assert_eq!(cfg.endpoint.as_deref(), Some("https://dav.internal"));
+    }
+
+    #[test]
+    fn from_uri_propagates_disable_copy() {
+        let uri = OperatorUri::new(
+            "webdav://dav.example.com".parse().unwrap(),
+            vec![("disable_copy".to_string(), "true".to_string())],
+        )
+        .unwrap();
+
+        let cfg = WebdavConfig::from_uri(&uri).unwrap();
+        assert!(cfg.disable_copy);
+    }
+}
diff --git a/core/src/services/webhdfs/backend.rs b/core/src/services/webhdfs/backend.rs
index 369a458c3..39dee3e89 100644
--- a/core/src/services/webhdfs/backend.rs
+++ b/core/src/services/webhdfs/backend.rs
@@ -40,18 +40,11 @@ use crate::services::WebhdfsConfig;
 use crate::*;
 const WEBHDFS_DEFAULT_ENDPOINT: &str = "http://127.0.0.1:9870";
 
-impl Configurator for WebhdfsConfig {
-    type Builder = WebhdfsBuilder;
-    fn into_builder(self) -> Self::Builder {
-        WebhdfsBuilder { config: self }
-    }
-}
-
 /// [WebHDFS](https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/WebHDFS.html)'s REST API support.
 #[doc = include_str!("docs.md")]
 #[derive(Default, Clone)]
 pub struct WebhdfsBuilder {
-    config: WebhdfsConfig,
+    pub(super) config: WebhdfsConfig,
 }
 
 impl Debug for WebhdfsBuilder {
diff --git a/core/src/services/webhdfs/config.rs b/core/src/services/webhdfs/config.rs
index 03dadfcaf..3b33ff03f 100644
--- a/core/src/services/webhdfs/config.rs
+++ b/core/src/services/webhdfs/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::WebhdfsBuilder;
 
 /// Config for WebHDFS support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -50,3 +51,11 @@ impl Debug for WebhdfsConfig {
             .finish_non_exhaustive()
     }
 }
+
+impl crate::Configurator for WebhdfsConfig {
+    type Builder = WebhdfsBuilder;
+    fn into_builder(self) -> Self::Builder {
+        WebhdfsBuilder { config: self }
+    }
+}
+
diff --git a/core/src/services/yandex_disk/backend.rs b/core/src/services/yandex_disk/backend.rs
index 133db49ae..e793b3867 100644
--- a/core/src/services/yandex_disk/backend.rs
+++ b/core/src/services/yandex_disk/backend.rs
@@ -34,26 +34,15 @@ use super::writer::YandexDiskWriters;
 use crate::raw::*;
 use crate::services::YandexDiskConfig;
 use crate::*;
-impl Configurator for YandexDiskConfig {
-    type Builder = YandexDiskBuilder;
-
-    #[allow(deprecated)]
-    fn into_builder(self) -> Self::Builder {
-        YandexDiskBuilder {
-            config: self,
-            http_client: None,
-        }
-    }
-}
 
 /// [YandexDisk](https://360.yandex.com/disk/) services support.
 #[doc = include_str!("docs.md")]
 #[derive(Default)]
 pub struct YandexDiskBuilder {
-    config: YandexDiskConfig,
+    pub(super) config: YandexDiskConfig,
 
     #[deprecated(since = "0.53.0", note = "Use `Operator::update_http_client` instead")]
-    http_client: Option<HttpClient>,
+    pub(super) http_client: Option<HttpClient>,
 }
 
 impl Debug for YandexDiskBuilder {
diff --git a/core/src/services/yandex_disk/config.rs b/core/src/services/yandex_disk/config.rs
index 27f3dc2c6..5b9c2561e 100644
--- a/core/src/services/yandex_disk/config.rs
+++ b/core/src/services/yandex_disk/config.rs
@@ -20,6 +20,7 @@ use std::fmt::Formatter;
 
 use serde::Deserialize;
 use serde::Serialize;
+use super::backend::YandexDiskBuilder;
 
 /// Config for YandexDisk services support.
 #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
@@ -43,3 +44,16 @@ impl Debug for YandexDiskConfig {
         ds.finish()
     }
 }
+
+impl crate::Configurator for YandexDiskConfig {
+    type Builder = YandexDiskBuilder;
+
+    #[allow(deprecated)]
+    fn into_builder(self) -> Self::Builder {
+        YandexDiskBuilder {
+            config: self,
+            http_client: None,
+        }
+    }
+}
+