Explorar o código

go.net/websocket: fix handshake error.

If client sent no subprotocol (e.g. no Sec-WebSocket-Protocol),
websocket server responded with the following header
  HTTP/1.1 101 Switching Protocols
  Upgrade: websocket
  Connection: Upgrade
  Sec-WebSocket-Accept: E7SRWRnZL9RuGFLuZ0j4508nqdg=
  Sec-WebSocket-Protocol:
So, client may close the connection because it contains
wrong empty Sec-WebSocket-Protocol header.

If client didn't offer any subprotocol, don't set
config.Protocol, so that not emit empty Sec-WebSocket-Protocol.

Fixes golang/go#5457.

R=golang-dev, mikioh.mikioh
CC=golang-dev
https://golang.org/cl/9379044
Fumitoshi Ukai %!s(int64=12) %!d(string=hai) anos
pai
achega
4c1c96f7e0
Modificáronse 2 ficheiros con 56 adicións e 4 borrados
  1. 6 3
      websocket/hybi.go
  2. 50 1
      websocket/hybi_test.go

+ 6 - 3
websocket/hybi.go

@@ -516,9 +516,11 @@ func (c *hybiServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Reques
 		return http.StatusBadRequest, err
 	}
 	protocol := strings.TrimSpace(req.Header.Get("Sec-Websocket-Protocol"))
-	protocols := strings.Split(protocol, ",")
-	for i := 0; i < len(protocols); i++ {
-		c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
+	if protocol != "" {
+		protocols := strings.Split(protocol, ",")
+		for i := 0; i < len(protocols); i++ {
+			c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
+		}
 	}
 	c.accept, err = getNonceAccept([]byte(key))
 	if err != nil {
@@ -546,6 +548,7 @@ func Origin(config *Config, req *http.Request) (*url.URL, error) {
 func (c *hybiServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err error) {
 	if len(c.Protocol) > 0 {
 		if len(c.Protocol) != 1 {
+			// You need choose a Protocol in Handshake func in Server.
 			return ErrBadWebSocketProtocol
 		}
 	}

+ 50 - 1
websocket/hybi_test.go

@@ -243,10 +243,14 @@ Sec-WebSocket-Version: 13
 	if code != http.StatusSwitchingProtocols {
 		t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
 	}
+	expectedProtocols := []string{"chat", "superchat"}
+	if fmt.Sprintf("%v", config.Protocol) != fmt.Sprintf("%v", expectedProtocols) {
+		t.Errorf("protocol expected %q but got %q", expectedProtocols, config.Protocol)
+	}
 	b := bytes.NewBuffer([]byte{})
 	bw := bufio.NewWriter(b)
 
-	config.Protocol = []string{"chat"}
+	config.Protocol = config.Protocol[:1]
 
 	err = handshaker.AcceptHandshake(bw)
 	if err != nil {
@@ -265,6 +269,51 @@ Sec-WebSocket-Version: 13
 	}
 }
 
+func TestHybiServerHandshakeNoSubProtocol(t *testing.T) {
+	config := new(Config)
+	handshaker := &hybiServerHandshaker{Config: config}
+	br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
+Host: server.example.com
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
+Origin: http://example.com
+Sec-WebSocket-Version: 13
+
+`))
+	req, err := http.ReadRequest(br)
+	if err != nil {
+		t.Fatal("request", err)
+	}
+	code, err := handshaker.ReadHandshake(br, req)
+	if err != nil {
+		t.Errorf("handshake failed: %v", err)
+	}
+	if code != http.StatusSwitchingProtocols {
+		t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
+	}
+	if len(config.Protocol) != 0 {
+		t.Errorf("len(config.Protocol) expected 0, but got %q", len(config.Protocol))
+	}
+	b := bytes.NewBuffer([]byte{})
+	bw := bufio.NewWriter(b)
+
+	err = handshaker.AcceptHandshake(bw)
+	if err != nil {
+		t.Errorf("handshake response failed: %v", err)
+	}
+	expectedResponse := strings.Join([]string{
+		"HTTP/1.1 101 Switching Protocols",
+		"Upgrade: websocket",
+		"Connection: Upgrade",
+		"Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
+		"", ""}, "\r\n")
+
+	if b.String() != expectedResponse {
+		t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
+	}
+}
+
 func TestHybiServerHandshakeHybi08(t *testing.T) {
 	config := new(Config)
 	handshaker := &hybiServerHandshaker{Config: config}