client.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. // Copyright 2013 Gary Burd. 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. package websocket
  5. import (
  6. "errors"
  7. "net"
  8. "net/http"
  9. "net/url"
  10. "strings"
  11. )
  12. // ErrBadHandshake is returned when the server response to opening handshake is
  13. // invalid.
  14. var ErrBadHandshake = errors.New("websocket: bad handshake")
  15. // NewClient creates a new client connection using the given net connection.
  16. // The URL u specifies the host and request URI. Use requestHeader to specify
  17. // the origin (Origin), subprotocols (Set-WebSocket-Protocol) and cookies
  18. // (Cookie). Use the response.Header to get the selected subprotocol
  19. // (Sec-WebSocket-Protocol) and cookies (Set-Cookie).
  20. //
  21. // If the WebSocket handshake fails, ErrBadHandshake is returned along with a
  22. // non-nil *http.Response so that callers can handle redirects, authentication,
  23. // etc.
  24. func NewClient(netConn net.Conn, u *url.URL, requestHeader http.Header, readBufSize, writeBufSize int) (c *Conn, response *http.Response, err error) {
  25. challengeKey, err := generateChallengeKey()
  26. if err != nil {
  27. return nil, nil, err
  28. }
  29. acceptKey := computeAcceptKey(challengeKey)
  30. c = newConn(netConn, false, readBufSize, writeBufSize)
  31. p := c.writeBuf[:0]
  32. p = append(p, "GET "...)
  33. p = append(p, u.RequestURI()...)
  34. p = append(p, " HTTP/1.1\r\nHost: "...)
  35. p = append(p, u.Host...)
  36. p = append(p, "\r\nUpgrade: websocket\r\nConnection: upgrade\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: "...)
  37. p = append(p, challengeKey...)
  38. p = append(p, "\r\n"...)
  39. for k, vs := range requestHeader {
  40. for _, v := range vs {
  41. p = append(p, k...)
  42. p = append(p, ": "...)
  43. p = append(p, v...)
  44. p = append(p, "\r\n"...)
  45. }
  46. }
  47. p = append(p, "\r\n"...)
  48. if _, err := netConn.Write(p); err != nil {
  49. return nil, nil, err
  50. }
  51. resp, err := http.ReadResponse(c.br, &http.Request{Method: "GET", URL: u})
  52. if err != nil {
  53. return nil, nil, err
  54. }
  55. if resp.StatusCode != 101 ||
  56. !strings.EqualFold(resp.Header.Get("Upgrade"), "websocket") ||
  57. !strings.EqualFold(resp.Header.Get("Connection"), "upgrade") ||
  58. resp.Header.Get("Sec-Websocket-Accept") != acceptKey {
  59. return nil, resp, ErrBadHandshake
  60. }
  61. return c, resp, nil
  62. }