@@ -5998,6 +5998,22 @@ func (s *GatewayService) handleStreamingResponse(ctx context.Context, resp *http
59985998 intervalCh = intervalTicker .C
59995999 }
60006000
6001+ // 下游 keepalive:防止代理/Cloudflare Tunnel 因连接空闲而断开
6002+ keepaliveInterval := time .Duration (0 )
6003+ if s .cfg != nil && s .cfg .Gateway .StreamKeepaliveInterval > 0 {
6004+ keepaliveInterval = time .Duration (s .cfg .Gateway .StreamKeepaliveInterval ) * time .Second
6005+ }
6006+ var keepaliveTicker * time.Ticker
6007+ if keepaliveInterval > 0 {
6008+ keepaliveTicker = time .NewTicker (keepaliveInterval )
6009+ defer keepaliveTicker .Stop ()
6010+ }
6011+ var keepaliveCh <- chan time.Time
6012+ if keepaliveTicker != nil {
6013+ keepaliveCh = keepaliveTicker .C
6014+ }
6015+ lastDataAt := time .Now ()
6016+
60016017 // 仅发送一次错误事件,避免多次写入导致协议混乱(写失败时尽力通知客户端)
60026018 errorEventSent := false
60036019 sendErrorEvent := func (reason string ) {
@@ -6187,6 +6203,7 @@ func (s *GatewayService) handleStreamingResponse(ctx context.Context, resp *http
61876203 break
61886204 }
61896205 flusher .Flush ()
6206+ lastDataAt = time .Now ()
61906207 }
61916208 if data != "" {
61926209 if firstTokenMs == nil && data != "[DONE]" {
@@ -6220,6 +6237,22 @@ func (s *GatewayService) handleStreamingResponse(ctx context.Context, resp *http
62206237 }
62216238 sendErrorEvent ("stream_timeout" )
62226239 return & streamingResult {usage : usage , firstTokenMs : firstTokenMs }, fmt .Errorf ("stream data interval timeout" )
6240+
6241+ case <- keepaliveCh :
6242+ if clientDisconnected {
6243+ continue
6244+ }
6245+ if time .Since (lastDataAt ) < keepaliveInterval {
6246+ continue
6247+ }
6248+ // SSE ping 事件:Anthropic 原生格式,客户端会正确处理,
6249+ // 同时保持连接活跃防止 Cloudflare Tunnel 等代理断开
6250+ if _ , werr := fmt .Fprint (w , "event: ping\n data: {\" type\" : \" ping\" }\n \n " ); werr != nil {
6251+ clientDisconnected = true
6252+ logger .LegacyPrintf ("service.gateway" , "Client disconnected during keepalive ping, continuing to drain upstream for billing" )
6253+ continue
6254+ }
6255+ flusher .Flush ()
62236256 }
62246257 }
62256258
0 commit comments