package user import ( "bytes" "encoding/json" "io" "net/http" "strings" "testing" "yunyan/lego/utils/crypto/aes" "yunyan/pb" ) // 联调用:打一次线上接口,解密后反序列化成对象,方便打断点看数据。改下面三个常量即可。 // // go test ./modules/user/ -run TestApiProbe -v // // probeKey 留空 = 不解密(v1 之类不加密的接口)。⚠️ 数据含明文凭据,别外传。 const ( probeURL = "https://echomeet.voitrans.net/api/home/user_getappconfig_v2" probeToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJFYXJwaG9uZSIsInN1YiI6IlNnaW4iLCJuYmYiOjE3ODY3NjEzNTYsImlhdCI6MTc4Njc2MTM1NiwianRpIjoiMjA4ODQ1NDYxNjI2MDgwNDYwOCJ9.tAkiUVNNEJMF4_Gfl1qYseUmh73CWcU5Ls9govEOtEQ" probeKey = "83KNTeWwQ4GiQHhlNJH1H8RyN88HNUOf" // 该环境 .env 里的 GATEWAY_ENCRYPT_KEY ) // probeResult 换接口时把 Data 的类型改掉即可: // // user_getappconfig / _v2 → pb.UserGetAppConfigResp // user_getappconfig_v3 → pb.UserGetAppConfigV3Resp // user_getthirdsvcs_v2 → pb.UserGetThirdSvcsResp // user_getagents_v2 / _v3 → pb.UserGetAgentsResp / pb.UserGetAgentsV3Resp type probeResult struct { Code int `json:"code"` Msg string `json:"msg"` Data pb.UserGetAppConfigResp `json:"data"` } func TestApiProbe(t *testing.T) { req, _ := http.NewRequest(http.MethodPost, probeURL, bytes.NewBufferString("{}")) req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", probeToken) resp, err := http.DefaultClient.Do(req) if err != nil { t.Fatalf("请求失败: %v", err) } defer resp.Body.Close() raw, _ := io.ReadAll(resp.Body) body := string(raw) if resp.Header.Get("X-Encrypted") == "1" { if probeKey == "" { t.Fatal("响应是加密的,请先填 probeKey(该环境的 GATEWAY_ENCRYPT_KEY)") } body = aes.AesDecryptCBC(strings.TrimSpace(body), probeKey) if !strings.HasPrefix(strings.TrimSpace(body), "{") { t.Fatalf("解密失败:probeKey 与该环境的 GATEWAY_ENCRYPT_KEY 不一致(长度须 16/24/32,当前 %d)", len(probeKey)) } } // ① 强类型对象——断点看它,字段能直接展开 var result probeResult if err := json.Unmarshal([]byte(body), &result); err != nil { t.Fatalf("反序列化失败: %v", err) } env := result.Data.Env agents := result.Data.Agents mcps := result.Data.Mcps products := result.Data.Products // ② 通用对象——换了接口懒得改 Data 类型时,看这个 var generic map[string]interface{} _ = json.Unmarshal([]byte(body), &generic) // 断点打在这一行,watch: result / env / mcps / generic t.Logf("code=%d msg=%s | env=%d agents=%d mcps=%d products=%d", result.Code, result.Msg, len(env), len(agents), len(mcps), len(products)) for k, v := range env { t.Logf(" env[%s] = %s", k, v) } for id, m := range mcps { t.Logf(" mcp[%s] name=%s url=%s type=%v tools=%s", id, m.Servername, m.Url, m.Type, m.Tools) } for _, a := range agents { t.Logf(" agent id=%s name=%s", a.Id, a.Name) } }