fix(trace): 令牌守卫上移进 trace.UpstreamError,构造即安全
M48 复审的中危 finding:error.type 里的散文经 trace.UpstreamError 原样出镜,
因为守卫加在调用方(M46 的 model/voice 两处),构造函数自己不套守卫 ——
任何新调用点默认不安全,httpclient / vision / embedding / weixin 四条出口一直漏。
- trace.UpstreamError 构造时对 error.code / error.type 各走一次 ErrorToken
([A-Za-z0-9_.-]{<=64},不合规即空串):默认安全,不是可选加固。
- 构造后注入这条窄路收进 UpstreamErrorInfo.SetCode / SetType(同一道守卫),
供 DashScope 顶层 code 与 Anthropic 流内 error.type 两处使用 —— 调用方不再
各抄一份 ErrorToken。
- 删除因此冗余的调用方守卫:model.providerUpstreamError 与
voice.dashscopeOKBodyError。保留 voice 的 request_id 守卫(它不是 code/type,
构造函数看不见)。
- 四条漏的出口一行没改,只加用例证明守卫上移后自动安全;摘掉构造函数守卫时
四条用例 + model/voice 旧用例同时变红。
This commit is contained in:
1 parent
4e9cd17fbd
commit
fe3872ee28
10 files changed
+419
-17
No files matched your search
@@ -41,7 +41,13 @@ func classifyDashscopeStatus(endpoint string, status int, contentType string, bo
|
||||
// helper 的构造是固定的,走不到这里;真走到也只少一条诊断。
|
||||
return fmt.Errorf("voice: %w", sentinel)
|
||||
}
|
||||
info.Code = trace.ErrorToken(fields.code)
|
||||
// 🔴 DashScope 把错误码放在**顶层** code 上(不是 error.code),构造函数看不见它,
|
||||
// 因此这里属于「构造后注入」:走 SetCode(同一道令牌守卫)。这不是重复守卫 ——
|
||||
// 去掉了它,散文形态的顶层 code 就会直接出镜(TestDashscopeTTS_Non200DropsFreeTextCode
|
||||
// 会变红)。
|
||||
info.SetCode(fields.code)
|
||||
// request_id 不进 UpstreamErrorInfo,也不由构造函数解析:它是被**拼进错误文本**的
|
||||
// 第三个自由文本面,所以它的守卫只能留在这里(这不是「同一件事守两遍」)。
|
||||
if rid := trace.ErrorToken(fields.requestID); rid != "" {
|
||||
return fmt.Errorf("voice: %w: request_id=%s: %w", sentinel, rid, info)
|
||||
}
|
||||
@@ -98,15 +104,14 @@ func decodeDashscopeErrorFields(body []byte) dashscopeErrorFields {
|
||||
// message 原文一律不进 error:它是上游自由文本,而这条请求的 input.url 是参考
|
||||
// 音频的公开地址(可能是预签名 URL,带凭据),上游报错经常把它整段回显出来。
|
||||
// 病因分类保留在 ErrProviderFailed(再试也不会好,与既有的熔断口径一致);
|
||||
// 确实带回来的 code/type 也只以令牌形态出镜(过 trace.ErrorToken)。
|
||||
// 确实带回来的 code/type 由 trace.UpstreamError **构造时**过令牌守卫(M49 上移),
|
||||
// 这里不再守第二遍。
|
||||
func dashscopeOKBodyError(endpoint string, body []byte) error {
|
||||
info, ok := trace.UpstreamError(trace.HostOf(endpoint), http.StatusOK, "", body).(*trace.UpstreamErrorInfo)
|
||||
if !ok {
|
||||
// helper 的构造是固定的,走不到这里;真走到也只少一条诊断。
|
||||
return fmt.Errorf("voice: %w: dashscope reported a business failure on a 200 response", ErrProviderFailed)
|
||||
}
|
||||
info.Code = trace.ErrorToken(info.Code)
|
||||
info.Type = trace.ErrorToken(info.Type)
|
||||
return fmt.Errorf("voice: %w: dashscope reported a business failure on a 200 response: %w",
|
||||
ErrProviderFailed, info)
|
||||
}
|
||||
Reference in new issue
Block a user