fix(sse): 系统模型 - 恢复 SSE 增量传输

集成 PR #257,保留原 PR 开发者为提交作者。
This commit is contained in:
MasterChiefCN authored and ddCat committed 2026-08-19 20:32:46 +08:00
1 parent d2a35e10d8
commit cd42afdfdd
7 files changed
+233 -14

No files matched your search

+21 -9
View File
@@ -829,13 +829,27 @@ func proxySystemRequest(c *gin.Context, svc *service.Service, user *model.User,
status = model.ApiCallStatusFailed
}
responseLimit := policy.Request.SystemRelayResponseMB << 20
responseBody, readErr := io.ReadAll(io.LimitReader(resp.Body, responseLimit+1))
streamed := isSystemProxyEventStream(resp)
var responseBody []byte
var readErr error
if streamed {
responseBody, readErr = streamSystemProxyResponse(c, resp, responseLimit)
} else {
responseBody, readErr = io.ReadAll(io.LimitReader(resp.Body, responseLimit+1))
}
if readErr != nil {
status = model.ApiCallStatusFailed
errorText = readErr.Error()
_ = svc.MarkBillingUncertain(billingOrderID, "系统渠道响应读取失败,费用状态待核对")
logSystemProxyCall(svc, apiCallLog(user, channel, billingOrderID, capability, protocol, c.Request.Method, path, target, body, c.GetHeader("Content-Type"), status, statusCode, time.Since(startedAt), errorText, concurrencyLimit), nil)
fail(c, http.StatusBadGateway, errors.New("系统渠道响应读取失败"))
billingNote := "系统渠道响应读取失败,费用状态待核对"
if errors.Is(readErr, errSystemProxyResponseTooLarge) {
billingNote = "上游已响应但流式响应体超过限制,费用状态待核对"
}
_ = svc.MarkBillingUncertain(billingOrderID, billingNote)
logSystemProxyCall(svc, apiCallLog(user, channel, billingOrderID, capability, protocol, c.Request.Method, path, target, body, c.GetHeader("Content-Type"), status, statusCode, time.Since(startedAt), errorText, concurrencyLimit), responseBody)
// SSE 响应头已经发送,流中断后只能关闭连接;非流式响应仍返回结构化错误。
if !streamed {
fail(c, http.StatusBadGateway, errors.New("系统渠道响应读取失败"))
}
return
}
if int64(len(responseBody)) > responseLimit {
@@ -855,12 +869,10 @@ func proxySystemRequest(c *gin.Context, svc *service.Service, user *model.User,
} else {
_ = svc.RefundBilling(billingOrderID, "上游明确返回失败")
}
for _, key := range []string{"Content-Type", "Cache-Control", "Content-Disposition"} {
if value := resp.Header.Get(key); value != "" {
c.Header(key, value)
}
if streamed {
return
}
c.Header("X-Content-Type-Options", "nosniff")
copySystemProxyResponseHeaders(c, resp)
c.Data(resp.StatusCode, resp.Header.Get("Content-Type"), responseBody)
}