优化: 代理工具代码审查修复

This commit is contained in:
2026-04-01 18:11:06 +08:00
parent f77ed2572a
commit 38b16a6efc
9 changed files with 321 additions and 91 deletions

View File

@@ -188,14 +188,50 @@ pub struct DownloadRequest {
fn default_concurrency() -> usize { 4 }
/// 修复 MSYS/Git Bash 在 Windows 上的路径转换问题
/// MSYS 会把 /tmp/file 转为 C:/Users/.../Temp/file/home/user/file 转为 C:/Users/user/file
/// 检测并还原为 Unix 路径
fn fix_msys_remote_path(path: &str) -> String {
#[cfg(target_os = "windows")]
{
// 检测 Windows 绝对路径 (X:\... 或 X:/...)
let bytes = path.as_bytes();
if bytes.len() >= 2 && bytes[1] == b':' && (bytes[2] == b'/' || bytes[2] == b'\\') {
// 可能是 MSYS 转换后的路径,尝试还原
// 常见映射C:/Users/<user>/AppData/Local/Temp/<name> -> /tmp/<name>
if let Some(idx) = path.find("/AppData/Local/Temp/") {
let rest = &path[idx + "/AppData/Local/Temp/".len()..];
return format!("/tmp/{}", rest);
}
// 常见映射C:/Users/<user>/... -> /home/<user>/... (不太常见但以防万一)
if let Some(idx) = path.find("/Users/") {
let rest = &path[idx + "/Users/".len()..];
// 如果 rest 以数字开头MSYS 用户目录映射),跳过
// 格式: C:/Users/<user>/file -> /home/<user>/file
if let Some(slash_pos) = rest.find('/') {
let user = &rest[..slash_pos];
let file_path = &rest[slash_pos..];
return format!("/home/{}{}", user, file_path);
}
}
}
}
#[cfg(not(target_os = "windows"))]
{
let _ = path;
}
path.to_string()
}
pub async fn upload(
State(state): State<AppState>,
Json(req): Json<UploadRequest>,
) -> Result<Json<TransferResponse>, (StatusCode, Json<ErrorResponse>)> {
let (manager, logger) = &*state;
let server_names = list_server_names(manager);
let remote_path = fix_msys_remote_path(&req.remote_path);
let result = manager.upload(&req.server, &req.local_path, &req.remote_path, req.concurrency).await
let result = manager.upload(&req.server, &req.local_path, &remote_path, req.concurrency).await
.map_err(|e| {
logger.log(&LogEntry::new("/upload", "http").with_server(&req.server).with_error(&e.to_string()));
let usage = format!(
@@ -228,8 +264,9 @@ pub async fn download(
) -> Result<Json<TransferResponse>, (StatusCode, Json<ErrorResponse>)> {
let (manager, logger) = &*state;
let server_names = list_server_names(manager);
let remote_path = fix_msys_remote_path(&req.remote_path);
let result = manager.download(&req.server, &req.remote_path, &req.local_path, req.concurrency).await
let result = manager.download(&req.server, &remote_path, &req.local_path, req.concurrency).await
.map_err(|e| {
logger.log(&LogEntry::new("/download", "http").with_server(&req.server).with_error(&e.to_string()));
let usage = format!(