|
|
@@ -46,6 +46,12 @@ type Upgrader struct {
|
|
|
// CheckOrigin is nil, the host in the Origin header must not be set or
|
|
|
// must match the host of the request.
|
|
|
CheckOrigin func(r *http.Request) bool
|
|
|
+
|
|
|
+ // CompressionSupported specify if the server should attempt to negotiate per
|
|
|
+ // message compression (RFC 7692). Setting this value to true does not
|
|
|
+ // guarantee that compression will be supported. Currently only "no context
|
|
|
+ // takeover" modes are supported.
|
|
|
+ CompressionSupported bool
|
|
|
}
|
|
|
|
|
|
func (u *Upgrader) returnError(w http.ResponseWriter, r *http.Request, status int, reason string) (*Conn, error) {
|
|
|
@@ -100,6 +106,11 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
|
|
|
if r.Method != "GET" {
|
|
|
return u.returnError(w, r, http.StatusMethodNotAllowed, "websocket: method not GET")
|
|
|
}
|
|
|
+
|
|
|
+ if _, ok := responseHeader["Sec-Websocket-Extensions"]; ok {
|
|
|
+ return u.returnError(w, r, http.StatusInternalServerError, "websocket: application specific Sec-Websocket-Extensions headers are unsupported")
|
|
|
+ }
|
|
|
+
|
|
|
if !tokenListContainsValue(r.Header, "Sec-Websocket-Version", "13") {
|
|
|
return u.returnError(w, r, http.StatusBadRequest, "websocket: version != 13")
|
|
|
}
|
|
|
@@ -127,6 +138,18 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
|
|
|
|
|
|
subprotocol := u.selectSubprotocol(r, responseHeader)
|
|
|
|
|
|
+ // Negotiate PMCE
|
|
|
+ var compress bool
|
|
|
+ if u.CompressionSupported {
|
|
|
+ for _, ext := range parseExtensions(r.Header) {
|
|
|
+ if ext[""] != "permessage-deflate" {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ compress = true
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
var (
|
|
|
netConn net.Conn
|
|
|
br *bufio.Reader
|
|
|
@@ -152,6 +175,11 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
|
|
|
c := newConn(netConn, true, u.ReadBufferSize, u.WriteBufferSize)
|
|
|
c.subprotocol = subprotocol
|
|
|
|
|
|
+ if compress {
|
|
|
+ c.newCompressionWriter = compressNoContextTakeover
|
|
|
+ c.newDecompressionReader = decompressNoContextTakeover
|
|
|
+ }
|
|
|
+
|
|
|
p := c.writeBuf[:0]
|
|
|
p = append(p, "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: "...)
|
|
|
p = append(p, computeAcceptKey(challengeKey)...)
|
|
|
@@ -161,6 +189,9 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
|
|
|
p = append(p, c.subprotocol...)
|
|
|
p = append(p, "\r\n"...)
|
|
|
}
|
|
|
+ if compress {
|
|
|
+ p = append(p, "Sec-Websocket-Extensions: permessage-deflate; server_no_context_takeover; client_no_context_takeover\r\n"...)
|
|
|
+ }
|
|
|
for k, vs := range responseHeader {
|
|
|
if k == "Sec-Websocket-Protocol" {
|
|
|
continue
|