mirror of
https://gitee.com/wanwujie/sub2api
synced 2026-04-26 01:14:47 +08:00
fix: 修复 Chat Completions 编译错误和运行时 panic
1. 修复 WriteFilteredHeaders API 不兼容(2处): 将 s.cfg.Security.ResponseHeaders 改为 s.responseHeaderFilter, 因为 main 分支已将函数签名改为接受 *responseheaders.CompiledHeaderFilter 2. 修复 writer 生命周期导致的 nil pointer panic: ChatCompletions handler 替换了 c.Writer 但未恢复,导致 OpsErrorLogger 中间件的 defer 释放 opsCaptureWriter 后, Logger 中间件调用 c.Writer.Status() 触发空指针解引用。 通过保存并恢复 originalWriter 修复。 3. 为 chatCompletionsResponseWriter 添加防御性 Status() 和 Written() 方法,包含 nil 安全检查 4. 恢复 gateway.go 中被误删的 net/http import
This commit is contained in:
@@ -62,6 +62,7 @@ func (h *OpenAIGatewayHandler) ChatCompletions(c *gin.Context) {
|
|||||||
|
|
||||||
stream, _ := converted["stream"].(bool)
|
stream, _ := converted["stream"].(bool)
|
||||||
model, _ := converted["model"].(string)
|
model, _ := converted["model"].(string)
|
||||||
|
originalWriter := c.Writer
|
||||||
writer := newChatCompletionsResponseWriter(c.Writer, stream, includeUsage, model)
|
writer := newChatCompletionsResponseWriter(c.Writer, stream, includeUsage, model)
|
||||||
c.Writer = writer
|
c.Writer = writer
|
||||||
c.Request.Body = io.NopCloser(bytes.NewReader(convertedBody))
|
c.Request.Body = io.NopCloser(bytes.NewReader(convertedBody))
|
||||||
@@ -69,6 +70,7 @@ func (h *OpenAIGatewayHandler) ChatCompletions(c *gin.Context) {
|
|||||||
|
|
||||||
h.Responses(c)
|
h.Responses(c)
|
||||||
writer.Finalize()
|
writer.Finalize()
|
||||||
|
c.Writer = originalWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
type chatCompletionsResponseWriter struct {
|
type chatCompletionsResponseWriter struct {
|
||||||
@@ -167,6 +169,20 @@ func (w *chatCompletionsResponseWriter) SetPassthrough() {
|
|||||||
w.passthrough = true
|
w.passthrough = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *chatCompletionsResponseWriter) Status() int {
|
||||||
|
if w.ResponseWriter == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return w.ResponseWriter.Status()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *chatCompletionsResponseWriter) Written() bool {
|
||||||
|
if w.ResponseWriter == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return w.ResponseWriter.Written()
|
||||||
|
}
|
||||||
|
|
||||||
func (w *chatCompletionsResponseWriter) flushStreamBuffer() {
|
func (w *chatCompletionsResponseWriter) flushStreamBuffer() {
|
||||||
for {
|
for {
|
||||||
buf := w.streamBuf.Bytes()
|
buf := w.streamBuf.Bytes()
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package routes
|
package routes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/Wei-Shaw/sub2api/internal/config"
|
"github.com/Wei-Shaw/sub2api/internal/config"
|
||||||
"github.com/Wei-Shaw/sub2api/internal/handler"
|
"github.com/Wei-Shaw/sub2api/internal/handler"
|
||||||
"github.com/Wei-Shaw/sub2api/internal/server/middleware"
|
"github.com/Wei-Shaw/sub2api/internal/server/middleware"
|
||||||
|
|||||||
@@ -209,8 +209,8 @@ func (s *OpenAIGatewayService) buildChatCompletionsRequest(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *OpenAIGatewayService) handleChatCompletionsStreamingResponse(ctx context.Context, resp *http.Response, c *gin.Context, account *Account, startTime time.Time, originalModel, mappedModel string) (*chatStreamingResult, error) {
|
func (s *OpenAIGatewayService) handleChatCompletionsStreamingResponse(ctx context.Context, resp *http.Response, c *gin.Context, account *Account, startTime time.Time, originalModel, mappedModel string) (*chatStreamingResult, error) {
|
||||||
if s.cfg != nil {
|
if s.responseHeaderFilter != nil {
|
||||||
responseheaders.WriteFilteredHeaders(c.Writer.Header(), resp.Header, s.cfg.Security.ResponseHeaders)
|
responseheaders.WriteFilteredHeaders(c.Writer.Header(), resp.Header, s.responseHeaderFilter)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Header("Content-Type", "text/event-stream")
|
c.Header("Content-Type", "text/event-stream")
|
||||||
@@ -409,7 +409,9 @@ func (s *OpenAIGatewayService) handleChatCompletionsNonStreamingResponse(resp *h
|
|||||||
}
|
}
|
||||||
body = s.correctToolCallsInResponseBody(body)
|
body = s.correctToolCallsInResponseBody(body)
|
||||||
|
|
||||||
responseheaders.WriteFilteredHeaders(c.Writer.Header(), resp.Header, s.cfg.Security.ResponseHeaders)
|
if s.responseHeaderFilter != nil {
|
||||||
|
responseheaders.WriteFilteredHeaders(c.Writer.Header(), resp.Header, s.responseHeaderFilter)
|
||||||
|
}
|
||||||
|
|
||||||
contentType := "application/json"
|
contentType := "application/json"
|
||||||
if s.cfg != nil && !s.cfg.Security.ResponseHeaders.Enabled {
|
if s.cfg != nil && !s.cfg.Security.ResponseHeaders.Enabled {
|
||||||
|
|||||||
Reference in New Issue
Block a user