gofiber sse

package main

import (
	"bufio"
	"fmt"
	"log"
	"time"

	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/fiber/v2/middleware/cors"
	"github.com/valyala/fasthttp"
)

var index = []byte(`<!DOCTYPE html>
<html>
<body>

<h1>SSE Messages</h1>
<button id="stop">Stop</button>
<div id="debug"></div>
<div id="result"></div>

<script>
if(typeof(EventSource) !== "undefined") {
  let source = new EventSource("sse");
  document.getElementById("stop").onclick = function(event) {
    source.close();
  };
  source.onopen = function(event) {
    document.getElementById("debug").innerHTML += "Connection to server opened.<br>";
  };
  source.onmessage = function(event) {
    document.getElementById("result").innerHTML += event.data + "<br>";
  };
  source.onerror = function(event) {
    document.getElementById("debug").innerHTML += "EventSource failed.<br>";
  };
} else {
  document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
}
</script>

</body>
</html>
`)

func main() {
	// Fiber instance
	app := fiber.New(fiber.Config{
		CaseSensitive: true,
		ReadTimeout:   30 * time.Second,
		WriteTimeout:  30 * time.Second,
	})

	// CORS for external resources
	app.Use(cors.New(cors.Config{
		AllowOrigins:     "http://127.0.0.1:8080,http://localhost:8080",
		AllowHeaders:     "Cache-Control",
		AllowCredentials: true,
	}))

	app.Get("/", func(c *fiber.Ctx) error {
		c.Response().Header.SetContentType(fiber.MIMETextHTMLCharsetUTF8)

		return c.Status(fiber.StatusOK).Send(index)
	})

	app.Get("/sse", func(c *fiber.Ctx) error {
		c.Set("Content-Type", "text/event-stream")
		c.Set("X-Accel-Buffering", "no")
		c.Set("Cache-Control", "no-cache")
		c.Set("Connection", "keep-alive")
		c.Set("Transfer-Encoding", "chunked")

		c.Status(fiber.StatusOK).Context().SetBodyStreamWriter(fasthttp.StreamWriter(func(w *bufio.Writer) {
			fmt.Println("WRITER")
			var i int
			for {
				i++
				msg := fmt.Sprintf("%d - the time is %v", i, time.Now())
				fmt.Fprintf(w, "data: Message: %s\n\n", msg)
				fmt.Println(msg)

				err := w.Flush()
				if err != nil {
					// Refreshing page in web browser will establish a new
					// SSE connection, but only (the last) one is alive, so
					// dead connections must be closed here.
					fmt.Printf("Error while flushing: %v. Closing http connection.\n", err)

					break
				}
				time.Sleep(2 * time.Second)
			}
		}))

		return nil
	})

	// Start server
	log.Fatal(app.Listen(":8080"))
}

注意:必须加上超时时间,否则server端socket一直不会关闭。

posted @   卓能文  阅读(54)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示