https之beego+websocket
前言
上一篇我们说了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)
}
}
}
}
}
}