fix: 修复流式响应中 URL 的 & 被转义为 \u0026 的问题

新增 jsonMarshalRaw 使用 SetEscapeHTML(false) 替代 json.Marshal,
避免 HTML 字符转义导致客户端无法直接使用返回的 URL。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
huangenjun
2026-02-25 11:32:56 +08:00
parent 3c619a8da5
commit 65d4ca2563
2 changed files with 22 additions and 4 deletions

View File

@@ -1,6 +1,7 @@
package service package service
import ( import (
"bytes"
"context" "context"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
@@ -830,7 +831,7 @@ func (s *SoraGatewayService) writeSoraStream(c *gin.Context, model, content stri
}, },
}, },
} }
encoded, _ := json.Marshal(chunk) encoded, _ := jsonMarshalRaw(chunk)
if _, err := fmt.Fprintf(writer, "data: %s\n\n", encoded); err != nil { if _, err := fmt.Fprintf(writer, "data: %s\n\n", encoded); err != nil {
return nil, err return nil, err
} }
@@ -851,7 +852,7 @@ func (s *SoraGatewayService) writeSoraStream(c *gin.Context, model, content stri
}, },
}, },
} }
finalEncoded, _ := json.Marshal(finalChunk) finalEncoded, _ := jsonMarshalRaw(finalChunk)
if _, err := fmt.Fprintf(writer, "data: %s\n\n", finalEncoded); err != nil { if _, err := fmt.Fprintf(writer, "data: %s\n\n", finalEncoded); err != nil {
return &ms, err return &ms, err
} }
@@ -1052,6 +1053,23 @@ func (s *SoraGatewayService) normalizeSoraMediaURLs(urls []string) []string {
return output return output
} }
// jsonMarshalRaw 序列化 JSON不转义 &、<、> 等 HTML 字符,
// 避免 URL 中的 & 被转义为 \u0026 导致客户端无法直接使用。
func jsonMarshalRaw(v any) ([]byte, error) {
var buf bytes.Buffer
enc := json.NewEncoder(&buf)
enc.SetEscapeHTML(false)
if err := enc.Encode(v); err != nil {
return nil, err
}
// Encode 会追加换行符,去掉它
b := buf.Bytes()
if len(b) > 0 && b[len(b)-1] == '\n' {
b = b[:len(b)-1]
}
return b, nil
}
func buildSoraContent(mediaType string, urls []string) string { func buildSoraContent(mediaType string, urls []string) string {
switch mediaType { switch mediaType {
case "image": case "image":

View File

@@ -316,7 +316,7 @@ func (s *SoraGatewayService) processSoraSSEData(data string, originalModel strin
} }
} }
updatedData, err := json.Marshal(payload) updatedData, err := jsonMarshalRaw(payload)
if err != nil { if err != nil {
return "data: " + data, contentDelta, nil return "data: " + data, contentDelta, nil
} }
@@ -484,7 +484,7 @@ func (s *SoraGatewayService) flushSoraRewriteBuffer(buffer string, originalModel
if originalModel != "" { if originalModel != "" {
payload["model"] = originalModel payload["model"] = originalModel
} }
updatedData, err := json.Marshal(payload) updatedData, err := jsonMarshalRaw(payload)
if err != nil { if err != nil {
return "", "", err return "", "", err
} }