diff --git a/http/http.go b/http/http.go index 4378b21..47c110f 100644 --- a/http/http.go +++ b/http/http.go @@ -14,6 +14,7 @@ import ( "gitee.com/red-future---jilin-g/common/log/controller" "gitee.com/red-future---jilin-g/common/utils" "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/net/gclient" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/net/gsvc" "github.com/gogf/gf/v2/os/gtime" @@ -60,49 +61,86 @@ func doRequest(ctx context.Context, method string, url string, headers map[strin if err != nil { return } - client := Httpclient + client := Httpclient.Clone() + + // POST/PUT/DELETE请求都需要显式用ContentJson序列化body + if (method == http.MethodPost || method == http.MethodPut || method == http.MethodDelete) && len(data) > 0 { + client = client.ContentJson() + } + + // 最后设置headers,确保不会被ContentJson覆盖 if len(headers) > 0 { - client = Httpclient.Clone() client.SetHeaderMap(headers) } else { client.SetHeader("Authorization", g.RequestFromCtx(ctx).GetHeader("Authorization")) } - if method == http.MethodDelete && len(data) > 0 { // DELETE请求显式用ContentJson序列化body - client = client.ContentJson() + + // 修复:避免data...展开导致的双重包装问题 + // 当只有一个元素时,直接传递该元素,避免被包装成数组 + var response *gclient.Response + if len(data) == 1 { + response, err = client.DoRequest(ctx, method, url, data[0]) + } else { + response, err = client.DoRequest(ctx, method, url, data...) } - response, err := client.DoRequest(ctx, method, url, data...) if err != nil { return } defer response.Close() result := response.ReadAll() + + // 添加调试日志:打印原始响应 + g.Log().Debugf(ctx, "[HTTP] 原始响应: %s", string(result)) + + // 第三方API特例:RAGFlow等第三方API响应格式为{code,data,message}一层结构,直接解析原始JSON到target + // 内部API格式为{code:200,message:"",data:{...}}两层结构,需经过DefaultHandlerResponse二次解析 + // 判断依据:URL包含/api/v1/(不影响内部API调用) + isThirdPartyAPI := strings.Contains(url, "/api/v1/") + + if isThirdPartyAPI { + // 第三方API特例:直接解析原始JSON到target,不经过DefaultHandlerResponse + if err = gconv.Struct(result, target); err != nil { + return errors.New("第三方API响应解析失败: " + err.Error()) + } + g.Log().Debugf(ctx, "[HTTP] 第三方API直接解析target: %+v", target) + return + } + + // 内部API:保持原有逻辑,先解析为DefaultHandlerResponse,再提取data字段 resultStrut := &ghttp.DefaultHandlerResponse{} if err = gconv.Struct(result, &resultStrut); err != nil { // 修复:增加err检查 return errors.New("响应解析失败: " + err.Error()) } + + // 添加调试日志:打印解析后的结构 + g.Log().Debugf(ctx, "[HTTP] 解析后结构: Code=%d, Message=%s, Data类型=%T, Data值=%+v", + resultStrut.Code, resultStrut.Message, resultStrut.Data, resultStrut.Data) + if resultStrut.Code == 200 || resultStrut.Code == 0 { if err = gconv.Struct(resultStrut.Data, target); err != nil { // 修复:增加err检查 return errors.New("数据解析失败: " + err.Error()) } + // 添加调试日志:打印最终的target + g.Log().Debugf(ctx, "[HTTP] 最终target: %+v", target) } else { err = errors.New(resultStrut.Message) } return } func Get(ctx context.Context, url string, headers map[string]string, target any, data ...any) (err error) { - err = doRequest(ctx, http.MethodGet, url, headers, target, data) + err = doRequest(ctx, http.MethodGet, url, headers, target, data...) return } func Post(ctx context.Context, url string, headers map[string]string, target any, data ...any) (err error) { - err = doRequest(ctx, http.MethodPost, url, headers, target, data) + err = doRequest(ctx, http.MethodPost, url, headers, target, data...) return } func Put(ctx context.Context, url string, headers map[string]string, target any, data ...any) (err error) { - err = doRequest(ctx, http.MethodPut, url, headers, target, data) + err = doRequest(ctx, http.MethodPut, url, headers, target, data...) return } func Delete(ctx context.Context, url string, headers map[string]string, target any, data ...any) (err error) { - err = doRequest(ctx, http.MethodDelete, url, headers, target, data) + err = doRequest(ctx, http.MethodDelete, url, headers, target, data...) return } diff --git a/ragflow/client.go b/ragflow/client.go index 2fb04fe..128f2fb 100644 --- a/ragflow/client.go +++ b/ragflow/client.go @@ -149,7 +149,7 @@ func (c *Client) request(ctx context.Context, method, path string, body interfac g.Log().Infof(ctx, "RAGFlow请求体: %s", bodyJSON) } - // 创建新的HTTP客户端实例(避免共享状态) + // 使用common/http包 var headers = make(map[string]string) headers["Authorization"] = "Bearer " + c.APIKey headers["Content-Type"] = "application/json" @@ -161,7 +161,6 @@ func (c *Client) request(ctx context.Context, method, path string, body interfac case "PUT": err = http.Put(ctx, fullURL, headers, result, body) case "DELETE": - if body != nil { err = http.Delete(ctx, fullURL, headers, result, body) } else { diff --git a/ragflow/dataset.go b/ragflow/dataset.go index b74970b..c5ac88b 100644 --- a/ragflow/dataset.go +++ b/ragflow/dataset.go @@ -157,9 +157,6 @@ func (c *Client) ListDatasets(ctx context.Context, req *ListDatasetsReq) (*ListD return nil, err } - // 添加调试日志 - g.Log().Infof(ctx, "ListDatasets原始响应: code=%d, total=%d, data_len=%d", res.Code, res.Total, len(res.Data)) - if res.Code != 0 { return nil, gerror.Newf("list datasets failed: code=%d", res.Code) } diff --git a/ragflow/document.go b/ragflow/document.go index c6e39e0..4158ea1 100644 --- a/ragflow/document.go +++ b/ragflow/document.go @@ -208,7 +208,6 @@ func (c *Client) UploadDocumentFromText(ctx context.Context, datasetId, content, } respBody := resp.ReadAll() - g.Log().Debugf(ctx, "RAGFlow上传文档响应: %s", string(respBody)) if err := json.Unmarshal(respBody, &response); err != nil { g.Log().Errorf(ctx, "解析RAGFlow响应失败: %v, 原始响应: %s", err, string(respBody)) diff --git a/redis/types.go b/redis/types.go index f3dc0c7..1e5a83f 100644 --- a/redis/types.go +++ b/redis/types.go @@ -102,6 +102,7 @@ type ArchiveMessage struct { UserId string `json:"userId"` // 用户ID Platform string `json:"platform"` // 平台标识 SessionId string `json:"sessionId"` // RAGFlow Session ID + TenantId string `json:"tenantId"` // 租户ID Timestamp int64 `json:"timestamp"` // 发送时间戳 }