脱敏阿里云抠图结果下载错误

避免临时 OSS 签名 URL 进入日志和审计 metadata

补充结果下载错误脱敏单测
This commit is contained in:
2026-07-09 13:02:29 +00:00
parent 71d449cd1a
commit e796cefe9f
+72 -2
View File
@@ -358,7 +358,9 @@ impl MattingClient {
.get(url)
.send()
.await
.map_err(|error| MattingError::Upstream(format!("下载抠图结果失败:{error}")))?;
.map_err(|error| {
MattingError::Upstream(describe_result_download_transport_error(&error))
})?;
let status = response.status();
if !status.is_success() {
return Err(MattingError::Upstream(format!(
@@ -370,7 +372,9 @@ impl MattingClient {
.bytes()
.await
.map(|bytes| bytes.to_vec())
.map_err(|error| MattingError::Upstream(format!("读取抠图结果字节失败:{error}")))
.map_err(|error| {
MattingError::Upstream(describe_result_download_body_error(&error))
})
}
/// 把本地图片字节上传到 VIAPI 官方临时桶,返回可直接作为 ImageURL 的公网地址。
@@ -581,6 +585,48 @@ fn hmac_sha1_base64(key: &[u8], content: &[u8]) -> Result<String, MattingError>
Ok(base64::engine::general_purpose::STANDARD.encode(signer.finalize().into_bytes()))
}
fn describe_result_download_transport_error(error: &reqwest::Error) -> String {
sanitize_result_download_error_message(format!(
"下载抠图结果失败(transport={}, timeout={}, connect={}",
classify_reqwest_error(error),
error.is_timeout(),
error.is_connect()
))
}
fn describe_result_download_body_error(error: &reqwest::Error) -> String {
sanitize_result_download_error_message(format!(
"读取抠图结果字节失败(transport={}, timeout={}, connect={}",
classify_reqwest_error(error),
error.is_timeout(),
error.is_connect()
))
}
fn classify_reqwest_error(error: &reqwest::Error) -> &'static str {
if error.is_timeout() {
"timeout"
} else if error.is_connect() {
"connect"
} else if error.is_body() || error.is_decode() {
"body"
} else if error.is_request() {
"request"
} else {
"unknown"
}
}
fn sanitize_result_download_error_message(message: String) -> String {
if message.contains("OSSAccessKeyId=")
|| message.contains("Signature=")
|| message.contains("Expires=")
{
return "下载抠图结果失败(临时签名 URL 已脱敏)".to_string();
}
message
}
fn insert_header(
headers: &mut reqwest::header::HeaderMap,
name: &'static str,
@@ -710,4 +756,28 @@ mod tests {
.expect("x-acs-date should exist");
assert!(!date.contains('.'), "x-acs-date 不能带小数秒:{date}");
}
#[test]
fn result_download_error_message_redacts_signed_oss_url() {
let message = sanitize_result_download_error_message(
"下载抠图结果失败:error sending request for url (https://viapi-customer-temp.oss-cn-shanghai.aliyuncs.com/a.png?OSSAccessKeyId=ak&Expires=123&Signature=secret)".to_string(),
);
assert!(!message.contains("OSSAccessKeyId"));
assert!(!message.contains("Signature"));
assert!(!message.contains("Expires=123"));
assert_eq!(message, "下载抠图结果失败(临时签名 URL 已脱敏)");
}
#[test]
fn result_download_error_message_keeps_safe_text() {
let message = sanitize_result_download_error_message(
"下载抠图结果失败(transport=connect, timeout=false, connect=true".to_string(),
);
assert_eq!(
message,
"下载抠图结果失败(transport=connect, timeout=false, connect=true"
);
}
}