61 lines
1.3 KiB
Go
61 lines
1.3 KiB
Go
package websocket
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"net"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
)
|
|
|
|
var (
|
|
ErrBadHandshake = errors.New("bad handshake")
|
|
)
|
|
|
|
func NewClient(netConn net.Conn, u *url.URL, requestHeader http.Header) (c *Conn, response *http.Response, err error) {
|
|
key, err := calcKey()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
acceptKey := calcAcceptKey(key)
|
|
|
|
c = NewConn(netConn, false)
|
|
|
|
buf := bytes.NewBufferString("GET ")
|
|
buf.WriteString(u.RequestURI())
|
|
buf.WriteString(" HTTP/1.1\r\nHost: ")
|
|
buf.WriteString(u.Host)
|
|
buf.WriteString("\r\nUpgrade: websocket\r\nConnection: upgrade\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: ")
|
|
buf.WriteString(key)
|
|
buf.WriteString("\r\n")
|
|
|
|
for k, vs := range requestHeader {
|
|
for _, v := range vs {
|
|
buf.WriteString(k)
|
|
buf.WriteString(": ")
|
|
buf.WriteString(v)
|
|
buf.WriteString("\r\n")
|
|
}
|
|
}
|
|
|
|
buf.WriteString("\r\n")
|
|
p := buf.Bytes()
|
|
if _, err := netConn.Write(p); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
resp, err := http.ReadResponse(c.br, &http.Request{Method: "GET", URL: u})
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
if resp.StatusCode != 101 ||
|
|
!strings.EqualFold(resp.Header.Get("Upgrade"), "websocket") ||
|
|
!strings.EqualFold(resp.Header.Get("Connection"), "upgrade") ||
|
|
resp.Header.Get("Sec-Websocket-Accept") != acceptKey {
|
|
return nil, resp, ErrBadHandshake
|
|
}
|
|
return c, resp, nil
|
|
}
|