github.com/deis/deis@v1.13.5-0.20170519182049-1d9e59fbdbfc/Godeps/_workspace/src/golang.org/x/net/websocket/hybi_test.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package websocket 6 7 import ( 8 "bufio" 9 "bytes" 10 "fmt" 11 "io" 12 "net/http" 13 "net/url" 14 "strings" 15 "testing" 16 ) 17 18 // Test the getNonceAccept function with values in 19 // http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17 20 func TestSecWebSocketAccept(t *testing.T) { 21 nonce := []byte("dGhlIHNhbXBsZSBub25jZQ==") 22 expected := []byte("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=") 23 accept, err := getNonceAccept(nonce) 24 if err != nil { 25 t.Errorf("getNonceAccept: returned error %v", err) 26 return 27 } 28 if !bytes.Equal(expected, accept) { 29 t.Errorf("getNonceAccept: expected %q got %q", expected, accept) 30 } 31 } 32 33 func TestHybiClientHandshake(t *testing.T) { 34 b := bytes.NewBuffer([]byte{}) 35 bw := bufio.NewWriter(b) 36 br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 Switching Protocols 37 Upgrade: websocket 38 Connection: Upgrade 39 Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= 40 Sec-WebSocket-Protocol: chat 41 42 `)) 43 var err error 44 config := new(Config) 45 config.Location, err = url.ParseRequestURI("ws://server.example.com/chat") 46 if err != nil { 47 t.Fatal("location url", err) 48 } 49 config.Origin, err = url.ParseRequestURI("http://example.com") 50 if err != nil { 51 t.Fatal("origin url", err) 52 } 53 config.Protocol = append(config.Protocol, "chat") 54 config.Protocol = append(config.Protocol, "superchat") 55 config.Version = ProtocolVersionHybi13 56 57 config.handshakeData = map[string]string{ 58 "key": "dGhlIHNhbXBsZSBub25jZQ==", 59 } 60 err = hybiClientHandshake(config, br, bw) 61 if err != nil { 62 t.Errorf("handshake failed: %v", err) 63 } 64 req, err := http.ReadRequest(bufio.NewReader(b)) 65 if err != nil { 66 t.Fatalf("read request: %v", err) 67 } 68 if req.Method != "GET" { 69 t.Errorf("request method expected GET, but got %q", req.Method) 70 } 71 if req.URL.Path != "/chat" { 72 t.Errorf("request path expected /chat, but got %q", req.URL.Path) 73 } 74 if req.Proto != "HTTP/1.1" { 75 t.Errorf("request proto expected HTTP/1.1, but got %q", req.Proto) 76 } 77 if req.Host != "server.example.com" { 78 t.Errorf("request Host expected server.example.com, but got %v", req.Host) 79 } 80 var expectedHeader = map[string]string{ 81 "Connection": "Upgrade", 82 "Upgrade": "websocket", 83 "Sec-Websocket-Key": config.handshakeData["key"], 84 "Origin": config.Origin.String(), 85 "Sec-Websocket-Protocol": "chat, superchat", 86 "Sec-Websocket-Version": fmt.Sprintf("%d", ProtocolVersionHybi13), 87 } 88 for k, v := range expectedHeader { 89 if req.Header.Get(k) != v { 90 t.Errorf(fmt.Sprintf("%s expected %q but got %q", k, v, req.Header.Get(k))) 91 } 92 } 93 } 94 95 func TestHybiClientHandshakeWithHeader(t *testing.T) { 96 b := bytes.NewBuffer([]byte{}) 97 bw := bufio.NewWriter(b) 98 br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 Switching Protocols 99 Upgrade: websocket 100 Connection: Upgrade 101 Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= 102 Sec-WebSocket-Protocol: chat 103 104 `)) 105 var err error 106 config := new(Config) 107 config.Location, err = url.ParseRequestURI("ws://server.example.com/chat") 108 if err != nil { 109 t.Fatal("location url", err) 110 } 111 config.Origin, err = url.ParseRequestURI("http://example.com") 112 if err != nil { 113 t.Fatal("origin url", err) 114 } 115 config.Protocol = append(config.Protocol, "chat") 116 config.Protocol = append(config.Protocol, "superchat") 117 config.Version = ProtocolVersionHybi13 118 config.Header = http.Header(make(map[string][]string)) 119 config.Header.Add("User-Agent", "test") 120 121 config.handshakeData = map[string]string{ 122 "key": "dGhlIHNhbXBsZSBub25jZQ==", 123 } 124 err = hybiClientHandshake(config, br, bw) 125 if err != nil { 126 t.Errorf("handshake failed: %v", err) 127 } 128 req, err := http.ReadRequest(bufio.NewReader(b)) 129 if err != nil { 130 t.Fatalf("read request: %v", err) 131 } 132 if req.Method != "GET" { 133 t.Errorf("request method expected GET, but got %q", req.Method) 134 } 135 if req.URL.Path != "/chat" { 136 t.Errorf("request path expected /chat, but got %q", req.URL.Path) 137 } 138 if req.Proto != "HTTP/1.1" { 139 t.Errorf("request proto expected HTTP/1.1, but got %q", req.Proto) 140 } 141 if req.Host != "server.example.com" { 142 t.Errorf("request Host expected server.example.com, but got %v", req.Host) 143 } 144 var expectedHeader = map[string]string{ 145 "Connection": "Upgrade", 146 "Upgrade": "websocket", 147 "Sec-Websocket-Key": config.handshakeData["key"], 148 "Origin": config.Origin.String(), 149 "Sec-Websocket-Protocol": "chat, superchat", 150 "Sec-Websocket-Version": fmt.Sprintf("%d", ProtocolVersionHybi13), 151 "User-Agent": "test", 152 } 153 for k, v := range expectedHeader { 154 if req.Header.Get(k) != v { 155 t.Errorf(fmt.Sprintf("%s expected %q but got %q", k, v, req.Header.Get(k))) 156 } 157 } 158 } 159 160 func TestHybiServerHandshake(t *testing.T) { 161 config := new(Config) 162 handshaker := &hybiServerHandshaker{Config: config} 163 br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1 164 Host: server.example.com 165 Upgrade: websocket 166 Connection: Upgrade 167 Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== 168 Origin: http://example.com 169 Sec-WebSocket-Protocol: chat, superchat 170 Sec-WebSocket-Version: 13 171 172 `)) 173 req, err := http.ReadRequest(br) 174 if err != nil { 175 t.Fatal("request", err) 176 } 177 code, err := handshaker.ReadHandshake(br, req) 178 if err != nil { 179 t.Errorf("handshake failed: %v", err) 180 } 181 if code != http.StatusSwitchingProtocols { 182 t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code) 183 } 184 expectedProtocols := []string{"chat", "superchat"} 185 if fmt.Sprintf("%v", config.Protocol) != fmt.Sprintf("%v", expectedProtocols) { 186 t.Errorf("protocol expected %q but got %q", expectedProtocols, config.Protocol) 187 } 188 b := bytes.NewBuffer([]byte{}) 189 bw := bufio.NewWriter(b) 190 191 config.Protocol = config.Protocol[:1] 192 193 err = handshaker.AcceptHandshake(bw) 194 if err != nil { 195 t.Errorf("handshake response failed: %v", err) 196 } 197 expectedResponse := strings.Join([]string{ 198 "HTTP/1.1 101 Switching Protocols", 199 "Upgrade: websocket", 200 "Connection: Upgrade", 201 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=", 202 "Sec-WebSocket-Protocol: chat", 203 "", ""}, "\r\n") 204 205 if b.String() != expectedResponse { 206 t.Errorf("handshake expected %q but got %q", expectedResponse, b.String()) 207 } 208 } 209 210 func TestHybiServerHandshakeNoSubProtocol(t *testing.T) { 211 config := new(Config) 212 handshaker := &hybiServerHandshaker{Config: config} 213 br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1 214 Host: server.example.com 215 Upgrade: websocket 216 Connection: Upgrade 217 Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== 218 Origin: http://example.com 219 Sec-WebSocket-Version: 13 220 221 `)) 222 req, err := http.ReadRequest(br) 223 if err != nil { 224 t.Fatal("request", err) 225 } 226 code, err := handshaker.ReadHandshake(br, req) 227 if err != nil { 228 t.Errorf("handshake failed: %v", err) 229 } 230 if code != http.StatusSwitchingProtocols { 231 t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code) 232 } 233 if len(config.Protocol) != 0 { 234 t.Errorf("len(config.Protocol) expected 0, but got %q", len(config.Protocol)) 235 } 236 b := bytes.NewBuffer([]byte{}) 237 bw := bufio.NewWriter(b) 238 239 err = handshaker.AcceptHandshake(bw) 240 if err != nil { 241 t.Errorf("handshake response failed: %v", err) 242 } 243 expectedResponse := strings.Join([]string{ 244 "HTTP/1.1 101 Switching Protocols", 245 "Upgrade: websocket", 246 "Connection: Upgrade", 247 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=", 248 "", ""}, "\r\n") 249 250 if b.String() != expectedResponse { 251 t.Errorf("handshake expected %q but got %q", expectedResponse, b.String()) 252 } 253 } 254 255 func TestHybiServerHandshakeHybiBadVersion(t *testing.T) { 256 config := new(Config) 257 handshaker := &hybiServerHandshaker{Config: config} 258 br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1 259 Host: server.example.com 260 Upgrade: websocket 261 Connection: Upgrade 262 Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== 263 Sec-WebSocket-Origin: http://example.com 264 Sec-WebSocket-Protocol: chat, superchat 265 Sec-WebSocket-Version: 9 266 267 `)) 268 req, err := http.ReadRequest(br) 269 if err != nil { 270 t.Fatal("request", err) 271 } 272 code, err := handshaker.ReadHandshake(br, req) 273 if err != ErrBadWebSocketVersion { 274 t.Errorf("handshake expected err %q but got %q", ErrBadWebSocketVersion, err) 275 } 276 if code != http.StatusBadRequest { 277 t.Errorf("status expected %q but got %q", http.StatusBadRequest, code) 278 } 279 } 280 281 func testHybiFrame(t *testing.T, testHeader, testPayload, testMaskedPayload []byte, frameHeader *hybiFrameHeader) { 282 b := bytes.NewBuffer([]byte{}) 283 frameWriterFactory := &hybiFrameWriterFactory{bufio.NewWriter(b), false} 284 w, _ := frameWriterFactory.NewFrameWriter(TextFrame) 285 w.(*hybiFrameWriter).header = frameHeader 286 _, err := w.Write(testPayload) 287 w.Close() 288 if err != nil { 289 t.Errorf("Write error %q", err) 290 } 291 var expectedFrame []byte 292 expectedFrame = append(expectedFrame, testHeader...) 293 expectedFrame = append(expectedFrame, testMaskedPayload...) 294 if !bytes.Equal(expectedFrame, b.Bytes()) { 295 t.Errorf("frame expected %q got %q", expectedFrame, b.Bytes()) 296 } 297 frameReaderFactory := &hybiFrameReaderFactory{bufio.NewReader(b)} 298 r, err := frameReaderFactory.NewFrameReader() 299 if err != nil { 300 t.Errorf("Read error %q", err) 301 } 302 if header := r.HeaderReader(); header == nil { 303 t.Errorf("no header") 304 } else { 305 actualHeader := make([]byte, r.Len()) 306 n, err := header.Read(actualHeader) 307 if err != nil { 308 t.Errorf("Read header error %q", err) 309 } else { 310 if n < len(testHeader) { 311 t.Errorf("header too short %q got %q", testHeader, actualHeader[:n]) 312 } 313 if !bytes.Equal(testHeader, actualHeader[:n]) { 314 t.Errorf("header expected %q got %q", testHeader, actualHeader[:n]) 315 } 316 } 317 } 318 if trailer := r.TrailerReader(); trailer != nil { 319 t.Errorf("unexpected trailer %q", trailer) 320 } 321 frame := r.(*hybiFrameReader) 322 if frameHeader.Fin != frame.header.Fin || 323 frameHeader.OpCode != frame.header.OpCode || 324 len(testPayload) != int(frame.header.Length) { 325 t.Errorf("mismatch %v (%d) vs %v", frameHeader, len(testPayload), frame) 326 } 327 payload := make([]byte, len(testPayload)) 328 _, err = r.Read(payload) 329 if err != nil { 330 t.Errorf("read %v", err) 331 } 332 if !bytes.Equal(testPayload, payload) { 333 t.Errorf("payload %q vs %q", testPayload, payload) 334 } 335 } 336 337 func TestHybiShortTextFrame(t *testing.T) { 338 frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame} 339 payload := []byte("hello") 340 testHybiFrame(t, []byte{0x81, 0x05}, payload, payload, frameHeader) 341 342 payload = make([]byte, 125) 343 testHybiFrame(t, []byte{0x81, 125}, payload, payload, frameHeader) 344 } 345 346 func TestHybiShortMaskedTextFrame(t *testing.T) { 347 frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame, 348 MaskingKey: []byte{0xcc, 0x55, 0x80, 0x20}} 349 payload := []byte("hello") 350 maskedPayload := []byte{0xa4, 0x30, 0xec, 0x4c, 0xa3} 351 header := []byte{0x81, 0x85} 352 header = append(header, frameHeader.MaskingKey...) 353 testHybiFrame(t, header, payload, maskedPayload, frameHeader) 354 } 355 356 func TestHybiShortBinaryFrame(t *testing.T) { 357 frameHeader := &hybiFrameHeader{Fin: true, OpCode: BinaryFrame} 358 payload := []byte("hello") 359 testHybiFrame(t, []byte{0x82, 0x05}, payload, payload, frameHeader) 360 361 payload = make([]byte, 125) 362 testHybiFrame(t, []byte{0x82, 125}, payload, payload, frameHeader) 363 } 364 365 func TestHybiControlFrame(t *testing.T) { 366 frameHeader := &hybiFrameHeader{Fin: true, OpCode: PingFrame} 367 payload := []byte("hello") 368 testHybiFrame(t, []byte{0x89, 0x05}, payload, payload, frameHeader) 369 370 frameHeader = &hybiFrameHeader{Fin: true, OpCode: PongFrame} 371 testHybiFrame(t, []byte{0x8A, 0x05}, payload, payload, frameHeader) 372 373 frameHeader = &hybiFrameHeader{Fin: true, OpCode: CloseFrame} 374 payload = []byte{0x03, 0xe8} // 1000 375 testHybiFrame(t, []byte{0x88, 0x02}, payload, payload, frameHeader) 376 } 377 378 func TestHybiLongFrame(t *testing.T) { 379 frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame} 380 payload := make([]byte, 126) 381 testHybiFrame(t, []byte{0x81, 126, 0x00, 126}, payload, payload, frameHeader) 382 383 payload = make([]byte, 65535) 384 testHybiFrame(t, []byte{0x81, 126, 0xff, 0xff}, payload, payload, frameHeader) 385 386 payload = make([]byte, 65536) 387 testHybiFrame(t, []byte{0x81, 127, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}, payload, payload, frameHeader) 388 } 389 390 func TestHybiClientRead(t *testing.T) { 391 wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o', 392 0x89, 0x05, 'h', 'e', 'l', 'l', 'o', // ping 393 0x81, 0x05, 'w', 'o', 'r', 'l', 'd'} 394 br := bufio.NewReader(bytes.NewBuffer(wireData)) 395 bw := bufio.NewWriter(bytes.NewBuffer([]byte{})) 396 conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil) 397 398 msg := make([]byte, 512) 399 n, err := conn.Read(msg) 400 if err != nil { 401 t.Errorf("read 1st frame, error %q", err) 402 } 403 if n != 5 { 404 t.Errorf("read 1st frame, expect 5, got %d", n) 405 } 406 if !bytes.Equal(wireData[2:7], msg[:n]) { 407 t.Errorf("read 1st frame %v, got %v", wireData[2:7], msg[:n]) 408 } 409 n, err = conn.Read(msg) 410 if err != nil { 411 t.Errorf("read 2nd frame, error %q", err) 412 } 413 if n != 5 { 414 t.Errorf("read 2nd frame, expect 5, got %d", n) 415 } 416 if !bytes.Equal(wireData[16:21], msg[:n]) { 417 t.Errorf("read 2nd frame %v, got %v", wireData[16:21], msg[:n]) 418 } 419 n, err = conn.Read(msg) 420 if err == nil { 421 t.Errorf("read not EOF") 422 } 423 if n != 0 { 424 t.Errorf("expect read 0, got %d", n) 425 } 426 } 427 428 func TestHybiShortRead(t *testing.T) { 429 wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o', 430 0x89, 0x05, 'h', 'e', 'l', 'l', 'o', // ping 431 0x81, 0x05, 'w', 'o', 'r', 'l', 'd'} 432 br := bufio.NewReader(bytes.NewBuffer(wireData)) 433 bw := bufio.NewWriter(bytes.NewBuffer([]byte{})) 434 conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil) 435 436 step := 0 437 pos := 0 438 expectedPos := []int{2, 5, 16, 19} 439 expectedLen := []int{3, 2, 3, 2} 440 for { 441 msg := make([]byte, 3) 442 n, err := conn.Read(msg) 443 if step >= len(expectedPos) { 444 if err == nil { 445 t.Errorf("read not EOF") 446 } 447 if n != 0 { 448 t.Errorf("expect read 0, got %d", n) 449 } 450 return 451 } 452 pos = expectedPos[step] 453 endPos := pos + expectedLen[step] 454 if err != nil { 455 t.Errorf("read from %d, got error %q", pos, err) 456 return 457 } 458 if n != endPos-pos { 459 t.Errorf("read from %d, expect %d, got %d", pos, endPos-pos, n) 460 } 461 if !bytes.Equal(wireData[pos:endPos], msg[:n]) { 462 t.Errorf("read from %d, frame %v, got %v", pos, wireData[pos:endPos], msg[:n]) 463 } 464 step++ 465 } 466 } 467 468 func TestHybiServerRead(t *testing.T) { 469 wireData := []byte{0x81, 0x85, 0xcc, 0x55, 0x80, 0x20, 470 0xa4, 0x30, 0xec, 0x4c, 0xa3, // hello 471 0x89, 0x85, 0xcc, 0x55, 0x80, 0x20, 472 0xa4, 0x30, 0xec, 0x4c, 0xa3, // ping: hello 473 0x81, 0x85, 0xed, 0x83, 0xb4, 0x24, 474 0x9a, 0xec, 0xc6, 0x48, 0x89, // world 475 } 476 br := bufio.NewReader(bytes.NewBuffer(wireData)) 477 bw := bufio.NewWriter(bytes.NewBuffer([]byte{})) 478 conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, new(http.Request)) 479 480 expected := [][]byte{[]byte("hello"), []byte("world")} 481 482 msg := make([]byte, 512) 483 n, err := conn.Read(msg) 484 if err != nil { 485 t.Errorf("read 1st frame, error %q", err) 486 } 487 if n != 5 { 488 t.Errorf("read 1st frame, expect 5, got %d", n) 489 } 490 if !bytes.Equal(expected[0], msg[:n]) { 491 t.Errorf("read 1st frame %q, got %q", expected[0], msg[:n]) 492 } 493 494 n, err = conn.Read(msg) 495 if err != nil { 496 t.Errorf("read 2nd frame, error %q", err) 497 } 498 if n != 5 { 499 t.Errorf("read 2nd frame, expect 5, got %d", n) 500 } 501 if !bytes.Equal(expected[1], msg[:n]) { 502 t.Errorf("read 2nd frame %q, got %q", expected[1], msg[:n]) 503 } 504 505 n, err = conn.Read(msg) 506 if err == nil { 507 t.Errorf("read not EOF") 508 } 509 if n != 0 { 510 t.Errorf("expect read 0, got %d", n) 511 } 512 } 513 514 func TestHybiServerReadWithoutMasking(t *testing.T) { 515 wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o'} 516 br := bufio.NewReader(bytes.NewBuffer(wireData)) 517 bw := bufio.NewWriter(bytes.NewBuffer([]byte{})) 518 conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, new(http.Request)) 519 // server MUST close the connection upon receiving a non-masked frame. 520 msg := make([]byte, 512) 521 _, err := conn.Read(msg) 522 if err != io.EOF { 523 t.Errorf("read 1st frame, expect %q, but got %q", io.EOF, err) 524 } 525 } 526 527 func TestHybiClientReadWithMasking(t *testing.T) { 528 wireData := []byte{0x81, 0x85, 0xcc, 0x55, 0x80, 0x20, 529 0xa4, 0x30, 0xec, 0x4c, 0xa3, // hello 530 } 531 br := bufio.NewReader(bytes.NewBuffer(wireData)) 532 bw := bufio.NewWriter(bytes.NewBuffer([]byte{})) 533 conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil) 534 535 // client MUST close the connection upon receiving a masked frame. 536 msg := make([]byte, 512) 537 _, err := conn.Read(msg) 538 if err != io.EOF { 539 t.Errorf("read 1st frame, expect %q, but got %q", io.EOF, err) 540 } 541 } 542 543 // Test the hybiServerHandshaker supports firefox implementation and 544 // checks Connection request header include (but it's not necessary 545 // equal to) "upgrade" 546 func TestHybiServerFirefoxHandshake(t *testing.T) { 547 config := new(Config) 548 handshaker := &hybiServerHandshaker{Config: config} 549 br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1 550 Host: server.example.com 551 Upgrade: websocket 552 Connection: keep-alive, upgrade 553 Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== 554 Origin: http://example.com 555 Sec-WebSocket-Protocol: chat, superchat 556 Sec-WebSocket-Version: 13 557 558 `)) 559 req, err := http.ReadRequest(br) 560 if err != nil { 561 t.Fatal("request", err) 562 } 563 code, err := handshaker.ReadHandshake(br, req) 564 if err != nil { 565 t.Errorf("handshake failed: %v", err) 566 } 567 if code != http.StatusSwitchingProtocols { 568 t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code) 569 } 570 b := bytes.NewBuffer([]byte{}) 571 bw := bufio.NewWriter(b) 572 573 config.Protocol = []string{"chat"} 574 575 err = handshaker.AcceptHandshake(bw) 576 if err != nil { 577 t.Errorf("handshake response failed: %v", err) 578 } 579 expectedResponse := strings.Join([]string{ 580 "HTTP/1.1 101 Switching Protocols", 581 "Upgrade: websocket", 582 "Connection: Upgrade", 583 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=", 584 "Sec-WebSocket-Protocol: chat", 585 "", ""}, "\r\n") 586 587 if b.String() != expectedResponse { 588 t.Errorf("handshake expected %q but got %q", expectedResponse, b.String()) 589 } 590 }