Geen omschrijving
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

log_stream_routes.go 1.9KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. package routes
  2. import (
  3. "fmt"
  4. "net/http"
  5. "time"
  6. "git.x2erp.com/qdy/go-base/authbase"
  7. "git.x2erp.com/qdy/go-base/webx/router"
  8. "git.x2erp.com/qdy/go-svc-code/internal/opencode"
  9. )
  10. // RegisterLogStreamRoutes 注册日志流路由
  11. func RegisterLogStreamRoutes(ws *router.RouterService, process *opencode.Process) {
  12. // 日志流路由
  13. // 注意:这个路由需要直接处理 HTTP 流,不能使用标准的 router 包装
  14. // 我们将注册一个原始的 HTTP 处理器到 gin 引擎
  15. // 这个函数将由 main.go 中的额外注册调用
  16. }
  17. // LogStreamHandler 日志流的 HTTP 处理器(已包含TokenAuth认证)
  18. func LogStreamHandler(process *opencode.Process) http.HandlerFunc {
  19. // 创建内部处理器
  20. handler := func(w http.ResponseWriter, r *http.Request) {
  21. // 设置 SSE 头
  22. w.Header().Set("Content-Type", "text/event-stream")
  23. w.Header().Set("Cache-Control", "no-cache")
  24. w.Header().Set("Connection", "keep-alive")
  25. w.Header().Set("Access-Control-Allow-Origin", "*")
  26. flusher, ok := w.(http.Flusher)
  27. if !ok {
  28. http.Error(w, "Streaming unsupported", http.StatusInternalServerError)
  29. return
  30. }
  31. // 获取日志通道
  32. logChan := process.GetLogs()
  33. if logChan == nil {
  34. http.Error(w, "日志通道不可用", http.StatusInternalServerError)
  35. return
  36. }
  37. // 发送初始消息
  38. fmt.Fprintf(w, "data: 连接到 opencode 日志流\n\n")
  39. flusher.Flush()
  40. // 监听日志通道
  41. for {
  42. select {
  43. case log, ok := <-logChan:
  44. if !ok {
  45. // 通道关闭
  46. fmt.Fprintf(w, "data: 日志流已结束\n\n")
  47. flusher.Flush()
  48. return
  49. }
  50. // 发送日志
  51. fmt.Fprintf(w, "data: %s\n\n", log)
  52. flusher.Flush()
  53. case <-r.Context().Done():
  54. // 客户端断开连接
  55. return
  56. case <-time.After(30 * time.Second):
  57. // 发送心跳保持连接
  58. fmt.Fprintf(w, ": heartbeat\n\n")
  59. flusher.Flush()
  60. }
  61. }
  62. }
  63. // 包装TokenAuth中间件
  64. return authbase.TokenAuth(http.HandlerFunc(handler)).ServeHTTP
  65. }