mod adapters;
mod assets;
mod auth;
mod cache;
mod crypto;
mod engine;
mod error;
mod registry;
mod routes;
mod settings;
mod state;
mod transfer;
mod vault;
use clap::Parser;
#[derive(Parser)]
#[command(name = "safedrive", version, about)]
struct Cli {
#[arg(long, default_value = "127.0.0.1:5266")]
bind: String,
#[arg(long)]
data_dir: Option<std::path::PathBuf>,
#[arg(long, env = "SAFEDRIVE_ADMIN_PASSWORD")]
admin_password: Option<String>,
#[arg(long, env = "SAFEDRIVE_HTTP_PROXY")]
http_proxy: Option<String>,
#[arg(long, env = "SAFEDRIVE_HTTP_CA_CERT")]
http_ca_cert: Option<std::path::PathBuf>,
#[arg(long, env = "SAFEDRIVE_INSECURE_TLS", default_value_t = false)]
insecure_tls: bool,
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let cli = Cli::parse();
let data_dir = cli.data_dir.unwrap_or_else(|| {
dirs::home_dir()
.unwrap_or_else(|| ".".into())
.join(".safedrive")
});
std::fs::create_dir_all(&data_dir)?;
let log_dir = data_dir.join("logs");
std::fs::create_dir_all(&log_dir)?;
let (file_writer, _log_guard) =
tracing_appender::non_blocking(tracing_appender::rolling::daily(&log_dir, "safedrive.log"));
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
tracing_subscriber::registry()
.with(
tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| "safedrive=info,tower_http=warn".into()),
)
.with(tracing_subscriber::fmt::layer())
.with(
tracing_subscriber::fmt::layer()
.with_ansi(false)
.with_writer(file_writer),
)
.init();
if cli.admin_password.is_none() {
tracing::warn!(
"未设置 --admin-password / SAFEDRIVE_ADMIN_PASSWORD,API 免登录(仅建议本机使用)"
);
}
if cli.http_proxy.is_some() {
tracing::info!("已为上游数据源请求启用显式 HTTP 代理");
}
if let Some(path) = &cli.http_ca_cert {
tracing::info!("已加载上游 HTTP 附加 CA: {}", path.display());
}
if cli.insecure_tls {
tracing::warn!("已禁用上游 HTTPS 证书校验;仅应在临时抓包调试时使用");
}
let state = state::AppState::new_with_http_options(
data_dir,
cli.admin_password,
state::HttpClientOptions {
proxy: cli.http_proxy,
ca_cert: cli.http_ca_cert,
insecure_tls: cli.insecure_tls,
},
)?;
let app = routes::router(state);
let listener = tokio::net::TcpListener::bind(&cli.bind).await?;
tracing::info!("safedrive 已启动: http://{}", cli.bind);
axum::serve(listener, app).await?;
Ok(())
}