欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Https+Websocket+Nginx+Beego不得不说的那些事

程序员文章站 2022-05-04 19:53:54
...

前言

上一篇我们说了beego和websocket的具体用户,那么项目在改为https后,发现前端和后端无法连接的问题
具体包含 nginx的使用、前端ws调整、beego代码调整等几个坑。

Nginx配置路由转发和证书

以下是nginx配置Https信息,需要提前将两个证书文件放到nginx/conf/目录下。
配置好后nginx/sbin/nginx -s reload 重新加载。

server {
        listen       443 ssl;
        server_name  localhost;

        ssl_certificate      ***.org.pem;
        ssl_certificate_key  ***.org.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;	# 这里后端websocket与前端连接5分钟后超时断开。

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location /ws{					# 这里与前端js里路一定要配对一样。
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_redirect off;
            proxy_read_timeout 120;
            proxy_pass http://0.0.0.0:8080/ws;
        }

       location / {
            try_files /_not_exists_ @backend;
        }
		location @backend{
            proxy_pass http://127.0.0.1:8080;  # 这里为本服务器程序端口
        }
 }

前端代码

var ws = new WebSocket('ws://IP:8080/ws');
改为
var ws = new WebSocket('wss://证书所对应的域名/ws');

beego中代码

以下代码是controller核心部分代码,router等代码则不展示。

package controllers
import (
    "fmt"
    "github.com/astaxie/beego"
    "net/http"
    "github.com/gorilla/websocket"
)

type MySocketController struct {
    beego.Controller
}

// 以下这句话必须加,不然还是连不上
var upgrader = websocket.Upgrader{CheckOrigin: func(r *http.Request) bool {
    return true
},}

// 定义数据结构{"表格id1": {客户端浏览器id: true}, "表格id2": {客户端浏览器id: true}}
var tableClinets = make(map[string]map[*websocket.Conn]bool)

func (c *MySocketController) Get() {
    ws, err := upgrader.Upgrade(c.Ctx.ResponseWriter, c.Ctx.Request, nil)
    if err != nil{
        beego.Info(err)
    }
    defer ws.CloseHandler()
    
	// 这里是我用户的结构体,你可以按自己需要定义
    var msg models.RecvWs
    
    for {
        err := ws.ReadJSON(&msg)
        if err != nil {
            beego.Info("页面可能断开啦")
            for k,v := range tableClinets{
                if _,ok := v[ws];ok{
                    delete(v, ws)
                    if len(v) == 0{
                        delete(tableClinets,k)
                    }
                    fmt.Println(tableClinets)
                }
            }
            break
        }
     
        // 获取表格ID,判断是否存在数据结构中,不存在插入。
        tableId := msg.TableUuid
        if sockets, ok := tableClinets[tableId]; ok{
            if _, ok := sockets[ws]; !ok{
                sockets[ws] = true
            }
        }else{
			client_map := map[*websocket.Conn]bool{ws: true}
            tableClinets[tableId] = client_map
        }

        // 将获取的消息按表格ID广播出去
        clients := tableClinets[tableId]
        go func(msg models.RecvWs){
            // 开启协程去做一些操作,例如可以实时去修改库里的内容
        }(msg)
        
        // 将消息广播的同时要把自己的客户端除去,自己不能给自己广播。
		for client := range clients{
            if client != ws{
                err = client.WriteJSON(msg)
                if err != nil {
                    client.Close()
                    delete(clients, client)
                    if len(clients) == 0{
                        delete(tableClinets,msg.TableUuid)
                    }
                }
            }
        }
    }
}

示例

Https+Websocket+Nginx+Beego不得不说的那些事