Merge pull request #3083 from xzz0081/fix/non-streaming-content-type

fix: force Content-Type to application/json on non-streaming responses
This commit is contained in:
Wesley Liddick
2026-06-08 09:20:17 +08:00
committed by GitHub
3 changed files with 17 additions and 0 deletions
@@ -318,6 +318,12 @@ func (s *GatewayService) handleCCBufferedFromAnthropic(
if s.responseHeaderFilter != nil {
responseheaders.WriteFilteredHeaders(c.Writer.Header(), resp.Header, s.responseHeaderFilter)
}
// 非流式响应必须是 application/json。上游被强制流式后会返回
// Content-Type: text/event-stream,经 WriteFilteredHeaders 透传后会污染
// 响应头;而 c.Data/c.JSON 走 Gin 的 writeContentType(仅当头不存在时才设置),
// 无法覆盖已存在的 SSE 头。这里显式 Set 强制改回 JSON,避免下游中间层
// (如 new-api)按 Content-Type 误判为流式。
c.Writer.Header().Set("Content-Type", "application/json; charset=utf-8")
// Marshal then bytes-replace so tool name mapping is reversed at byte level
// (parity with Parrot non-stream flow that marshals → restore → emit).
if respBytes, err := json.Marshal(ccResp); err == nil {
@@ -337,6 +337,12 @@ func (s *GatewayService) handleResponsesBufferedStreamingResponse(
if s.responseHeaderFilter != nil {
responseheaders.WriteFilteredHeaders(c.Writer.Header(), resp.Header, s.responseHeaderFilter)
}
// 非流式响应必须是 application/json。上游被强制流式后会返回
// Content-Type: text/event-stream,经 WriteFilteredHeaders 透传后会污染
// 响应头;而 c.Data/c.JSON 走 Gin 的 writeContentType(仅当头不存在时才设置),
// 无法覆盖已存在的 SSE 头。这里显式 Set 强制改回 JSON,避免下游中间层
// (如 new-api)按 Content-Type 误判为流式。
c.Writer.Header().Set("Content-Type", "application/json; charset=utf-8")
if respBytes, err := json.Marshal(responsesResp); err == nil {
respBytes = reverseToolNamesIfPresent(c, respBytes)
c.Data(http.StatusOK, "application/json; charset=utf-8", respBytes)
@@ -407,6 +407,11 @@ func (s *OpenAIGatewayService) handleChatBufferedStreamingResponse(
if s.responseHeaderFilter != nil {
responseheaders.WriteFilteredHeaders(c.Writer.Header(), resp.Header, s.responseHeaderFilter)
}
// 非流式响应必须为标准 JSON。上游被强制流式,其响应头 Content-Type 为
// text/event-stream,会经 WriteFilteredHeaders 透传进来;而 c.JSON 走 Gin 的
// writeContentType 仅在头不存在时才设置,无法覆盖。这里显式 Set 强制改回 JSON,
// 否则下游"看头判流式"的中间层(如 new-api)会把本应聚合的 JSON 当成 SSE 处理。
c.Writer.Header().Set("Content-Type", "application/json; charset=utf-8")
c.JSON(http.StatusOK, chatResp)
return &OpenAIForwardResult{