2024-11-16 14:00:57 +08:00

98 lines
3.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//后端代码
//注意 **我注释的代码是不使用gin框架封装的Stream方法也就是C.Stream(func())和C.ssevent(),只是C.Stream要改成for循环持续的从通道里面进行读直到通道关闭结束for循环**
package main
import (
"catface/app/service/nlp/glm"
_ "catface/bootstrap"
"fmt"
"io"
"testing"
// "time"
"github.com/gin-gonic/gin"
)
func SSE(c *gin.Context) {
// 设置响应头告诉前端适用event-stream事件流交互
//c.Writer.Header().Set("Content-Type", "text/event-stream")
//c.Writer.Header().Set("Cache-Control", "no-cache")
//c.Writer.Header().Set("Connection", "keep-alive")
// 判断是否支持sse
//w := c.Writer
//flusher, _ := w.(http.Flusher)
query := c.Query("query")
// 接收前端页面关闭连接通知
closeNotify := c.Request.Context().Done()
// 开启协程监听前端页面是否关闭了连接,关闭连接会触发此方法
go func() {
<-closeNotify
fmt.Println("SSE关闭了")
return
}()
//新建一个通道,用于数据接收和响应
Chan := make(chan string)
// 异步接收GPT响应然后把响应的数据发送到通道Chan
go func() {
err := glm.ChatStream(query, Chan)
if err != nil {
fmt.Println("Error", err)
}
close(Chan)
}()
// gin框架封装的stream,会持续的调用这个func方法记得返回true;返回false代表结束调用func方法
c.Stream(func(w io.Writer) bool {
select {
case i, ok := <-Chan:
if !ok {
return false
}
c.SSEvent("chat", i) // c.SSEvent会自动修改响应头为事件流并发送”test“事件流给前端监听”test“的回调方法
//flusher.Flush() // 确保立即发送
return true
case <-closeNotify:
fmt.Println("SSE关闭了")
return false
}
})
}
func TestSSE(t *testing.T) {
engine := gin.Default()
// 设置跨域中间件
engine.Use(func(context *gin.Context) {
origin := context.GetHeader("Origin")
// 允许 Origin 字段中的域发送请求
context.Writer.Header().Add("Access-Control-Allow-Origin", origin) // 这边我的前端页面在63342会涉及跨域这个根据自己情况设置或者直接设置为”*“,放行所有的
// 设置预验请求有效期为 86400 秒
context.Writer.Header().Set("Access-Control-Max-Age", "86400")
// 设置允许请求的方法
context.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, U`PDATE, PATCH")
// 设置允许请求的 Header
context.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Apitoken")
// 设置拿到除基本字段外的其他字段如上面的Apitoken, 这里通过引用Access-Control-Expose-Headers进行配置效果是一样的。
context.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Headers")
// 配置是否可以带认证信息
context.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
// OPTIONS请求返回200
if context.Request.Method == "OPTIONS" {
fmt.Println(context.Request.Header)
context.AbortWithStatus(200)
} else {
context.Next()
}
})
engine.GET("/admin/rag/default_talk", SSE) // TIP 记得适用get请求我用post前端报404资料说是SSE只支持get请求
engine.Run(":20201")
}