2 Star 9 Fork 1

os-lee/easy-paas

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
proxy.go 2.44 KB
一键复制 编辑 原始数据 按行查看 历史
lee 提交于 2024-07-11 15:01 . websocket路由支持url重写,负载均衡
package middleware_ws
import (
"errors"
"gitee.com/os-lee/easy-paas/common"
"gitee.com/os-lee/easy-paas/common/e"
"gitee.com/os-lee/easy-paas/gateway/internal/dao"
"gitee.com/os-lee/easy-paas/gateway/internal/load_balancer"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
"net/http"
"net/url"
)
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
CheckOrigin: func(r *http.Request) bool {
// 允许任何来源的请求
return true
},
}
// Proxy 处理代理的WebSocket连接
func Proxy() gin.HandlerFunc {
return func(c *gin.Context) {
// 检查请求头是否为WebSocket请求
if c.Request.Header.Get("Upgrade") != "websocket" {
c.AbortWithStatus(http.StatusBadRequest)
return
}
// 解析目标URL
serverInterface, ok := c.Get("service")
if !ok {
common.ResponseError(c, e.ErrGateway, errors.New("从上下文中获取服务失败"))
c.AbortWithStatus(http.StatusBadRequest)
return
}
serviceDetail := serverInterface.(*dao.ServiceDetail)
lb, err := load_balancer.Handler.Get(serviceDetail)
targetURL, err := url.Parse(lb.Pick(c.Request).URL.String())
if err != nil || targetURL.Scheme == "" || targetURL.Host == "" {
c.AbortWithStatus(http.StatusBadRequest)
return
}
// 升级HTTP连接到WebSocket
src, err := upgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
defer src.Close()
// 连接到远程服务器
dialer := &websocket.Dialer{}
dest, _, err := dialer.Dial(targetURL.String(), nil)
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
defer dest.Close()
forwardMessages(src, dest)
c.Abort()
}
}
// 在两个WebSocket连接之间转发消息
func forwardMessages(src *websocket.Conn, dest *websocket.Conn) {
srcReadChan := make(chan []byte, 10)
destReadChan := make(chan []byte, 10)
go readMessages(src, srcReadChan)
go readMessages(dest, destReadChan)
for {
select {
case data := <-srcReadChan:
if err := dest.WriteMessage(websocket.TextMessage, data); err != nil {
break
}
case data := <-destReadChan:
if err := src.WriteMessage(websocket.TextMessage, data); err != nil {
break
}
}
}
}
// 从WebSocket连接读取消息并放入channel
func readMessages(conn *websocket.Conn, ch chan<- []byte) {
for {
_, data, err := conn.ReadMessage()
if err != nil {
close(ch)
return
}
ch <- data
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/os-lee/easy-paas.git
git@gitee.com:os-lee/easy-paas.git
os-lee
easy-paas
easy-paas
6cf1638f64c0

搜索帮助