feat(webdav): add WebDAV protocol gateway (#2158)

Signed-off-by: yxrxy <1532529704@qq.com>
Co-authored-by: houseme <housemecn@gmail.com>
Co-authored-by: 马登山 <Cxymds@qq.com>
Co-authored-by: heihutu <30542132+heihutu@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: 安正超 <anzhengchao@gmail.com>
This commit is contained in:
yxrxy
2026-03-14 23:06:53 +08:00
committed by GitHub
parent f66a90c1b2
commit d3cff7d033
21 changed files with 2265 additions and 8 deletions
+2 -1
View File
@@ -35,7 +35,8 @@ default = ["metrics"]
metrics = []
ftps = ["rustfs-protocols/ftps"]
swift = ["rustfs-protocols/swift"]
full = ["metrics", "ftps", "swift"]
webdav = ["rustfs-protocols/webdav"]
full = ["metrics", "ftps", "swift", "webdav"]
[lints]
workspace = true
+70
View File
@@ -508,3 +508,73 @@ pub async fn init_ftps_system() -> Result<Option<tokio::sync::broadcast::Sender<
Ok(Some(shutdown_tx))
}
}
/// Initialize the WebDAV system
///
/// This function initializes the WebDAV server if enabled in the configuration.
/// It sets up the WebDAV server with the appropriate configuration and starts
/// the server in a background task.
#[cfg(feature = "webdav")]
#[instrument(skip_all)]
pub async fn init_webdav_system() -> Result<Option<tokio::sync::broadcast::Sender<()>>, Box<dyn std::error::Error + Send + Sync>>
{
{
use crate::protocols::ProtocolStorageClient;
use rustfs_config::{
DEFAULT_WEBDAV_ADDRESS, ENV_WEBDAV_ADDRESS, ENV_WEBDAV_CA_FILE, ENV_WEBDAV_CERTS_DIR, ENV_WEBDAV_ENABLE,
ENV_WEBDAV_MAX_BODY_SIZE, ENV_WEBDAV_REQUEST_TIMEOUT, ENV_WEBDAV_TLS_ENABLED,
};
use rustfs_protocols::{WebDavConfig, WebDavServer};
// Check if WebDAV is enabled
let webdav_enable = rustfs_utils::get_env_bool(ENV_WEBDAV_ENABLE, false);
if !webdav_enable {
debug!("WebDAV system is disabled");
return Ok(None);
}
// Parse WebDAV address
let webdav_address_str = rustfs_utils::get_env_str(ENV_WEBDAV_ADDRESS, DEFAULT_WEBDAV_ADDRESS);
let addr = rustfs_utils::net::parse_and_resolve_address(&webdav_address_str)
.map_err(|e| format!("Invalid WebDAV address '{webdav_address_str}': {e}"))?;
// Get WebDAV configuration from environment variables
let tls_enabled = rustfs_utils::get_env_bool(ENV_WEBDAV_TLS_ENABLED, true);
let cert_dir = rustfs_utils::get_env_opt_str(ENV_WEBDAV_CERTS_DIR);
let ca_file = rustfs_utils::get_env_opt_str(ENV_WEBDAV_CA_FILE);
let max_body_size = rustfs_utils::get_env_u64(ENV_WEBDAV_MAX_BODY_SIZE, WebDavConfig::DEFAULT_MAX_BODY_SIZE);
let request_timeout_secs =
rustfs_utils::get_env_u64(ENV_WEBDAV_REQUEST_TIMEOUT, WebDavConfig::DEFAULT_REQUEST_TIMEOUT_SECS);
// Create WebDAV configuration
let config = WebDavConfig {
bind_addr: addr,
tls_enabled,
cert_dir,
ca_file,
max_body_size,
request_timeout_secs,
};
// Create WebDAV server with protocol storage client
let fs = crate::storage::ecfs::FS::new();
let storage_client = ProtocolStorageClient::new(fs);
let server: WebDavServer<crate::protocols::ProtocolStorageClient> = WebDavServer::new(config, storage_client).await?;
// Log server configuration
info!("WebDAV server configured on {}", server.config().bind_addr);
// Start WebDAV server in background task with proper shutdown support
let (shutdown_tx, shutdown_rx) = tokio::sync::broadcast::channel(1);
tokio::spawn(async move {
if let Err(e) = server.start(shutdown_rx).await {
error!("WebDAV server error: {}", e);
}
info!("WebDAV server shutdown completed");
});
info!("WebDAV system initialized successfully");
Ok(Some(shutdown_tx))
}
}
+36 -1
View File
@@ -21,7 +21,7 @@ mod error;
mod init;
mod license;
mod profiling;
#[cfg(feature = "ftps")]
#[cfg(any(feature = "ftps", feature = "webdav"))]
mod protocols;
mod server;
mod storage;
@@ -37,6 +37,9 @@ use crate::init::{
#[cfg(feature = "ftps")]
use crate::init::{init_ftp_system, init_ftps_system};
#[cfg(feature = "webdav")]
use crate::init::init_webdav_system;
use crate::server::{
SHUTDOWN_TIMEOUT, ServiceState, ServiceStateManager, ShutdownSignal, init_cert, init_event_notifier, shutdown_event_notifier,
start_audit_system, start_http_server, stop_audit_system, wait_for_shutdown,
@@ -348,6 +351,26 @@ async fn run(config: config::Config) -> Result<()> {
#[cfg(not(feature = "ftps"))]
let ftps_shutdown_tx: Option<tokio::sync::broadcast::Sender<()>> = None;
// Initialize WebDAV system if enabled
#[cfg(feature = "webdav")]
let webdav_shutdown_tx = match init_webdav_system().await {
Ok(Some(tx)) => {
info!("WebDAV system initialized successfully");
Some(tx)
}
Ok(None) => {
info!("WebDAV system disabled");
None
}
Err(e) => {
error!("Failed to initialize WebDAV system: {}", e);
return Err(Error::other(e));
}
};
#[cfg(not(feature = "webdav"))]
let webdav_shutdown_tx: Option<tokio::sync::broadcast::Sender<()>> = None;
// Initialize buffer profiling system
init_buffer_profile_system(&config);
@@ -471,6 +494,7 @@ async fn run(config: config::Config) -> Result<()> {
console_shutdown_tx,
ftp_shutdown_tx,
ftps_shutdown_tx,
webdav_shutdown_tx,
ctx.clone(),
)
.await;
@@ -483,6 +507,7 @@ async fn run(config: config::Config) -> Result<()> {
console_shutdown_tx,
ftp_shutdown_tx,
ftps_shutdown_tx,
webdav_shutdown_tx,
ctx.clone(),
)
.await;
@@ -500,6 +525,7 @@ async fn handle_shutdown(
console_shutdown_tx: Option<tokio::sync::broadcast::Sender<()>>,
ftp_shutdown_tx: Option<tokio::sync::broadcast::Sender<()>>,
ftps_shutdown_tx: Option<tokio::sync::broadcast::Sender<()>>,
webdav_shutdown_tx: Option<tokio::sync::broadcast::Sender<()>>,
ctx: CancellationToken,
) {
ctx.cancel();
@@ -552,6 +578,15 @@ async fn handle_shutdown(
let _ = ftps_shutdown_tx.send(());
}
// Shutdown WebDAV server
if let Some(webdav_shutdown_tx) = webdav_shutdown_tx {
info!(
target: "rustfs::main::handle_shutdown",
"Shutting down WebDAV server..."
);
let _ = webdav_shutdown_tx.send(());
}
// Stop the notification system
info!(
target: "rustfs::main::handle_shutdown",