Golang原生golang.org/x/net/websocket包跨域问题解决方法

142 阅读1分钟

问题

我们是用golang.org/x/net/websocket的时候是这样连接

websocket.Handler(func(conn *websocket.Conn) {
		websocket.Message.Send("连接成功")
	}).ServeHTTP(w, req)

使用Postman做Websocket连接测试的时候状态码报403

原因

但是以上方法前端发起请求的时候请求头中的Origin字段中的值需要为本站点的值,详情自行百度Origin的作用 我们可以进入ServeHTTP(w, rep)方法查看源码:

// ServeHTTP implements the http.Handler interface for a WebSocket
func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	s := Server{Handler: h, Handshake: checkOrigin}
	s.serveWebSocket(w, req)
}

func checkOrigin(config *Config, req *http.Request) (err error) {
	config.Origin, err = Origin(config, req)
	if err == nil && config.Origin == nil {
		return fmt.Errorf("null origin")
	}
	return err
}

// Origin parses the Origin header in req.
// If the Origin header is not set, it returns nil and nil.
func Origin(config *Config, req *http.Request) (*url.URL, error) {
	var origin string
	switch config.Version {
	case ProtocolVersionHybi13:
		origin = req.Header.Get("Origin")
	}
	if origin == "" {
		return nil, nil
	}
	return url.ParseRequestURI(origin)
}

从上面源码的调用链可以看出对请求头中的Origin字段做了校验

解决方案

websocket.Server{
		Handler: func(ws *websocket.Conn) {
			websocket.Message.Send("连接成功")
		},
		Handshake: func(config *websocket.Config, req *http.Request) error {
			// 解决跨域问题 源码参考 net/websocket/server.go:110
			return nil
		},
	}.ServeHTTP(w, r)

注意使用的是golang.org/x/net/websocket包 当然如果再请求头里面添加Origin字段滴值也是可以,Postman默认是不添加Origin的值滴

不对之处请多指教!!!