mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-04-13 13:30:31 +08:00
feat: mask sensitive parts of a subscription URL for safe logging
This commit is contained in:
parent
119aaee546
commit
fa07dfbc9a
@ -65,7 +65,7 @@ pub async fn enhance_profiles() -> CmdResult {
|
||||
/// 导入配置文件
|
||||
#[tauri::command]
|
||||
pub async fn import_profile(url: std::string::String, option: Option<PrfOption>) -> CmdResult {
|
||||
logging!(info, Type::Cmd, "[导入订阅] 开始导入: {}", url);
|
||||
logging!(info, Type::Cmd, "[导入订阅] 开始导入: {}", help::mask_url(&url));
|
||||
|
||||
// 直接依赖 PrfItem::from_url 自身的超时/重试逻辑,不再使用 tokio::time::timeout 包裹
|
||||
let item = &mut match PrfItem::from_url(&url, None, None, option.as_ref()).await {
|
||||
@ -107,7 +107,7 @@ pub async fn import_profile(url: std::string::String, option: Option<PrfOption>)
|
||||
handle::Handle::notify_profile_changed(uid);
|
||||
}
|
||||
|
||||
logging!(info, Type::Cmd, "[导入订阅] 导入完成: {}", url);
|
||||
logging!(info, Type::Cmd, "[导入订阅] 导入完成: {}", help::mask_url(&url));
|
||||
AutoBackupManager::trigger_backup(AutoBackupTrigger::ProfileChange);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ use crate::{
|
||||
cmd,
|
||||
config::{Config, PrfItem, PrfOption, profiles::profiles_draft_update_item_safe},
|
||||
core::{CoreManager, handle, tray},
|
||||
utils::help::mask_url,
|
||||
};
|
||||
use anyhow::{Result, bail};
|
||||
use clash_verge_logging::{Type, logging, logging_error};
|
||||
@ -83,9 +84,11 @@ async fn should_update_profile(uid: &String, ignore_auto_update: bool) -> Result
|
||||
Type::Config,
|
||||
"[订阅更新] {} 是远程订阅,URL: {}",
|
||||
uid,
|
||||
item.url
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow::anyhow!("Profile URL is None"))?
|
||||
mask_url(
|
||||
item.url
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow::anyhow!("Profile URL is None"))?
|
||||
)
|
||||
);
|
||||
Ok(Some((
|
||||
item.url.clone().ok_or_else(|| anyhow::anyhow!("Profile URL is None"))?,
|
||||
|
||||
@ -98,6 +98,57 @@ pub fn parse_str<T: FromStr>(target: &str, key: &str) -> Option<T> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Mask sensitive parts of a subscription URL for safe logging.
|
||||
/// Examples:
|
||||
/// - `https://example.com/api/v1/clash?token=abc123` → `https://example.com/api/v1/clash?token=***`
|
||||
/// - `https://example.com/abc123def456ghi789/clash` → `https://example.com/***/clash`
|
||||
pub fn mask_url(url: &str) -> String {
|
||||
// Split off query string
|
||||
let (path_part, query_part) = match url.find('?') {
|
||||
Some(pos) => (&url[..pos], Some(&url[pos + 1..])),
|
||||
None => (url, None),
|
||||
};
|
||||
|
||||
// Extract scheme+host prefix (everything up to the first '/' after "://")
|
||||
let host_end = path_part
|
||||
.find("://")
|
||||
.and_then(|scheme_end| {
|
||||
path_part[scheme_end + 3..]
|
||||
.find('/')
|
||||
.map(|slash| scheme_end + 3 + slash)
|
||||
})
|
||||
.unwrap_or(path_part.len());
|
||||
|
||||
let scheme_and_host = &path_part[..host_end];
|
||||
let path = &path_part[host_end..]; // starts with '/' or empty
|
||||
|
||||
let mut result = scheme_and_host.to_owned();
|
||||
|
||||
// Mask path segments that look like tokens (longer than 16 chars)
|
||||
if !path.is_empty() {
|
||||
let masked: Vec<&str> = path
|
||||
.split('/')
|
||||
.map(|seg| if seg.len() > 16 { "***" } else { seg })
|
||||
.collect();
|
||||
result.push_str(&masked.join("/"));
|
||||
}
|
||||
|
||||
// Keep query param keys, mask values
|
||||
if let Some(query) = query_part {
|
||||
result.push('?');
|
||||
let masked_query: Vec<String> = query
|
||||
.split('&')
|
||||
.map(|param| match param.find('=') {
|
||||
Some(eq) => format!("{}=***", ¶m[..eq]),
|
||||
None => param.to_owned(),
|
||||
})
|
||||
.collect();
|
||||
result.push_str(&masked_query.join("&"));
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
/// get the last part of the url, if not found, return empty string
|
||||
pub fn get_last_part_and_decode(url: &str) -> Option<String> {
|
||||
let path = url.split('?').next().unwrap_or(""); // Splits URL and takes the path part
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user