MENU

Golang Gin框架中实现Server Sent Events(SSE)

January 2, 2024 • Read: 5746 • 默认分类

被这个功能困扰了好久,一直没实现,因为网上的 Gin 框架实现的 SSE 都非常复杂,写成了一整套复杂的中间件,经过研究,写出了一套精简的实现。

SSE 接口代码,发送信息修改 sendEvents 内代码即可:

  • func GetTaskResult(c *gin.Context) {
  • tag := "compositioncontroller.GetTaskResult"
  • ctx := xesgin.TransferToContext(c)
  • var args proto.GetTaskResultReq
  • err := c.ShouldBind(&args)
  • if err != nil {
  • logger.Ix(ctx, tag, "c.ShouldBind failed", "err:[%+v]", err)
  • c.JSON(http.StatusOK, xesgin.Error(logger.NewError("", logger.PARAM_ERROR)))
  • return
  • }
  • err = compositionSvc.NewCompositionSvc().TaskResultStream(ctx, args, c.Writer)
  • if err != nil {
  • logger.Ix(ctx, tag, "compositionSvc.GetTaskResultStreaming failed", "err:[%+v]", err)
  • c.JSON(http.StatusOK, xesgin.Error(err))
  • return
  • }
  • }
  • // 流式响应任务结果
  • func (c *compositionSvc) TaskResultStream(ctx context.Context, args proto.GetTaskResultReq, w http.ResponseWriter) (err error) {
  • w.Header().Set("Content-Type", "text/event-stream")
  • w.Header().Set("Cache-Control", "no-cache")
  • w.Header().Set("Connection", "keep-alive")
  • w.Header().Set("Access-Control-Allow-Origin", "*")
  • closeNotifier := w.(http.CloseNotifier).CloseNotify()
  • stopCh := make(chan struct{})
  • go c.sendEvents(ctx, &args, w, stopCh)
  • <-closeNotifier
  • if _, ok := <-stopCh; ok {
  • close(stopCh)
  • }
  • return
  • }
  • func (c *compositionSvc) sendEvents(ctx context.Context, args *proto.GetTaskResultReq, w http.ResponseWriter, stopCh chan struct{}) {
  • tag := "compositionSvc.sendEvents"
  • var resp proto.GetTaskResultResp
  • for {
  • var data []string
  • select {
  • case <-time.After(time.Millisecond * 300):
  • data, err := redisRepo.Get(ctx, args.TaskId)
  • if err != nil {
  • logger.Ix(ctx, tag, "redisRepo.Get failed", "err:[%+v]", err)
  • return
  • }
  • if data.Content == "" {
  • continue
  • }
  • // 响应数据
  • respByte, err := json.Marshal(resp)
  • if err != nil {
  • logger.Ix(ctx, tag, "json.Marshal failed", "err:[%+v]", err)
  • return
  • }
  • sseData := fmt.Sprintf("data: %s\n\n", string(respByte))
  • _, err = io.WriteString(w, sseData)
  • if err != nil {
  • logger.Ix(ctx, tag, "io.WriteString failed", "err:[%+v]", err)
  • return
  • }
  • if flusher, ok := w.(http.Flusher); ok {
  • flusher.Flush()
  • }
  • if data.status == cast.ToString(aigc.TaskStatusSuccess) || data.status == cast.ToString(aigc.TaskStatusFail) {
  • return
  • }
  • case <-stopCh:
  • return
  • }
  • }
  • }
Last Modified: January 3, 2024
Leave a Comment

38 Comments
  1. 《宝贝》国产剧高清在线免费观看:https://www.jgz518.com/xingkong/142249.html

  2. 如果因为害怕失败,而不去努力,那就不会有能够成功的人。

  3. 你的文章让我感受到了快乐,每天都要来看一看。 http://www.55baobei.com/kVN9QbBteD.html

  4. 每次看到你的文章,我都觉得时间过得好快。 https://www.4006400989.com/qyvideo/70604.html

  5. 你的才华让人瞩目,期待你的更多文章。 https://www.yonboz.com/video/98175.html