Go handling websockets and HTTP with the same handler

huangapple go评论90阅读模式
英文:

Go handling websockets and HTTP with the same handler

问题

我已经搜索了一段时间,但没有找到直接回答这个问题的内容。

Go语言能够处理WebSocket连接和HTTP连接使用相同的处理程序吗?

简而言之,我想复制类似SignalR的功能。

英文:

Been scouring for a while but couldn't find anything that directly answers this.

Can Go handle WS connections and HTTP connections using the same handler?

In short, I'd like to replicate something like SignalR

答案1

得分: 2

是的,gorilla/websocket包支持在请求处理程序中从HTTP升级到WebSocket。请参考包文档的开头中的示例。函数handler是一个标准的HTTP请求处理程序。调用upgrader.Upgrade将连接切换到WebSocket协议。

而x/net/websocket包需要一个单独的处理程序。还有其他原因,你可能不想使用x/net/websocket包。

英文:

Yes, the gorilla/websocket package supports upgrade from HTTP to WebSocket in a request handler. See the example at the beginning of the package documentation. The function handler is a standard HTTP request handler. The call to upgrader.Upgrade switches the connection to the WebSocket protocol.

The x/net/websocket package requires a separate handler. There are other reasons why you probably don't want to use the x/net/websocket package.

答案2

得分: 2

我最终需要在将请求传递给upgrader.upgrade方法之前自己对请求进行过滤。因为upgrader.upgrade在无法升级请求时,会将"Bad request"的响应写入其中。这将导致我的HTML以纯文本形式呈现,并在开头附加"Bad request"文本。

所以这是我在handler函数顶部所做的事情:

func singleHandler(w http.ResponseWriter, r *http.Request) {
	upgrade := false
	for _, header := range r.Header["Upgrade"] {
		if header == "websocket" {
			upgrade = true
			break
		}
	}

	if upgrade == false {
		if r.Method != "GET" {
			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
			return
		}
		if r.URL.Path != "/" {
			http.NotFound(w, r)
			return
		}
		chatTemplate.Execute(w, listenAddr)
		return
	}

	c, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Print("Upgrade err:", err)
		return
	}

	...
}

这是一个示例仓库:https://github.com/siriusdely/gochat。基于Andrew Gerrand的演讲:code that grows with grace https://talks.golang.org/2012/chat.slide#44

英文:

I ended up needing to filter the request myself before passing it to upgrader.upgrade method. Because upgrader.upgrade, upon failing to upgrade the request, write 'Bad request' response to it. Something that will render my HTML as plain text with additional 'Bad request' text in the beginning.

So this is what I do at the top of the handler:

func singleHandler(w http.ResponseWriter, r *http.Request) {
	upgrade := false
	for _, header := range r.Header["Upgrade"] {
		if header == "websocket" {
			upgrade = true
			break
		}
	}

	if upgrade == false {
		if r.Method != "GET" {
			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
			return
		}
		if r.URL.Path != "/" {
			http.NotFound(w, r)
			return
		}
		chatTemplate.Execute(w, listenAddr)
		return
	}

	c, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Print("Upgrade err:", err)
		return
	}

	...
}

Here is an example repo: https://github.com/siriusdely/gochat. Based on Andrew Gerrand's talk: code that grows with grace https://talks.golang.org/2012/chat.slide#44.

huangapple
  • 本文由 发表于 2014年12月11日 03:30:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/27409296.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定