前言
上一篇我们说了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)
                    }
                }
            }
        }
    }
}