-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathws.go
107 lines (91 loc) · 2.8 KB
/
ws.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package silverlining
import (
"crypto/sha1"
"encoding/base64"
"errors"
"io"
"net/http"
"strings"
"github.com/gobwas/ws"
)
var ErrUpgradeBadRequest = errors.New("upgrade request is not valid")
var wsMagic = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
func (r *Context) writeUpgradeWebSocket() error {
Upgrade, ok := r.RequestHeaders().Get("Upgrade")
if !ok {
r.ResponseHeaders().Set("Content-Type", "text/plain")
r.WriteFullBodyString(400, "Missing Upgrade header")
return ErrUpgradeBadRequest
}
if Upgrade != "websocket" && strings.EqualFold(Upgrade, "websocket") {
r.ResponseHeaders().Set("Content-Type", "text/plain")
r.WriteFullBodyString(400, "Invalid Upgrade header")
return ErrUpgradeBadRequest
}
Connection, ok := r.RequestHeaders().Get("Connection")
if !ok {
r.ResponseHeaders().Set("Content-Type", "text/plain")
r.WriteFullBodyString(400, "Missing Connection header")
return ErrUpgradeBadRequest
}
if !strings.EqualFold(Connection, "Upgrade") {
r.ResponseHeaders().Set("Content-Type", "text/plain")
r.WriteFullBodyString(400, "Sorry, only \"Upgrade\" connection is supported")
return ErrUpgradeBadRequest
}
SecVersion, ok := r.RequestHeaders().Get("Sec-WebSocket-Version")
if !ok {
r.ResponseHeaders().Set("Content-Type", "text/plain")
r.WriteFullBodyString(400, "Missing Sec-WebSocket-Version header")
return ErrUpgradeBadRequest
}
if SecVersion != "13" {
r.ResponseHeaders().Set("Content-Type", "text/plain")
r.WriteFullBodyString(400, "Sorry, only WebSocket version 13 is supported.")
return ErrUpgradeBadRequest
}
SecKey, ok := r.RequestHeaders().Get("Sec-WebSocket-Key")
if !ok {
r.ResponseHeaders().Set("Content-Type", "text/plain")
r.WriteFullBodyString(400, "Missing Sec-WebSocket-Key header")
return ErrUpgradeBadRequest
}
if len(SecKey) < 24 {
r.ResponseHeaders().Set("Content-Type", "text/plain")
r.WriteFullBodyString(400, "Invalid Sec-WebSocket-Key header")
return ErrUpgradeBadRequest
}
r.ResponseHeaders().Set("Connection", "Upgrade")
r.ResponseHeaders().Set("Upgrade", "Websocket")
h := sha1.New()
h.Write(stringToBytes(SecKey))
h.Write(wsMagic)
r.ResponseHeaders().Set("Sec-WebSocket-Accept", base64.StdEncoding.EncodeToString(h.Sum(nil)))
r.WriteHeader(http.StatusSwitchingProtocols)
err := r.Flush()
if err != nil {
return err
}
return nil
}
// Upgrade the request to WebSocket protocol.
// param:
// op: the opcode to use for the WebSocket connection. (ws.OpText|ws.OpBinary)
func (r *Context) UpgradeWebSocket(op ws.OpCode) (brwc io.ReadWriteCloser, err error) {
err = r.writeUpgradeWebSocket()
if err != nil {
return nil, err
}
bufR, _, conn := r.HijackConn()
type ReadWriteCloserConn struct {
io.Reader
io.Writer
io.Closer
}
brwc = ReadWriteCloserConn{
Reader: bufR,
Writer: conn,
Closer: conn,
}
return
}