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