近期在用GoFrame框架使用websocket时根据官方给出的案例创建websocket

golang 服务端

package main

import (
    "github.com/gogf/gf/frame/g"
    "github.com/gogf/gf/net/ghttp"
    "github.com/gogf/gf/os/gfile"
    "github.com/gogf/gf/os/glog"
)

func main() {
    s := g.Server()
    s.BindHandler("/ws", func(r *ghttp.Request) {
        ws, err := r.WebSocket()
        if err != nil {
            glog.Error(err)
            r.Exit()
        }
        for {
            msgType, msg, err := ws.ReadMessage()
            if err != nil {
                return
            }
            if err = ws.WriteMessage(msgType, msg); err != nil {
                return
            }
        }
    })
    s.SetServerRoot(gfile.MainPkgPath())
    s.SetPort(8199)
    s.Run()
}

客户端

$(function () {
    var url = "ws://127.0.0.1:8199/ws";
    var ws  = new WebSocket(url);
    try {
        // ws连接成功
        ws.onopen = function () {
            showInfo("WebSocket Server [" + url +"] 连接成功!");
        };
        // ws连接关闭
        ws.onclose = function () {
            if (ws) {
                ws.close();
                ws = null;
            }
            showError("WebSocket Server [" + url +"] 连接关闭!");
        };
        // ws连接错误
        ws.onerror = function () {
            if (ws) {
                ws.close();
                ws = null;
            }
            showError("WebSocket Server [" + url +"] 连接关闭!");
        };
        // ws数据返回处理
        ws.onmessage = function (result) {
            showWaring(" > " + result.data);
        };
    } catch (e) {
        alert(e.message);
    }
})

可以正常连接成功,但在使用token后报错:

var url = "ws://127.0.0.1:8199/ws";
var token = "tokentest"
var ws  = new WebSocket(url, token);

报错信息:

WebSocket connection to 'ws://127.0.0.1:8199/ws' failed: Error during WebSocket handshake: Sent non-empty 'Sec-WebSocket-Protocol' header but no response was received

查看请求头发现,请求头中多出了 Sec-WebSocket-Protocol 来记录token。
服务端需要对请求头中的 Sec-WebSocket-Protocol 进行特殊处理。

修改服务端websocket创建代码:

package main

import (
    "github.com/gogf/gf/frame/g"
    "github.com/gogf/gf/net/ghttp"
    "github.com/gogf/gf/os/gfile"
    "github.com/gogf/gf/os/glog"
    "github.com/gogf/gf/third/github.com/gorilla/websocket"
    "net/http"
)

func main() {
    s := g.Server()
    s.BindHandler("/ws", func(r *ghttp.Request) {
        upgrade := &websocket.Upgrader{
            // 检测请求来源
            CheckOrigin: func(r *http.Request) bool {
                return true
            },
            Subprotocols:[]string{r.Request.Header.Get("Sec-WebSocket-Protocol")},
        }

        responseWriter := r.Response.ResponseWriter.ResponseWriter
        ws, err := upgrade.Upgrade(responseWriter, r.Request, nil)
        if err != nil {
            glog.Error(err)
            r.Exit()
        }
        for {
            msgType, msg, err := ws.ReadMessage()
            if err != nil {
                return
            }
            if err = ws.WriteMessage(msgType, msg); err != nil {
                return
            }
        }
    })
    s.SetServerRoot(gfile.MainPkgPath())
    s.SetPort(8199)
    s.Run()
}

成功!