@@ -46,6 +46,12 @@ type Upgrader struct {
46
46
// CheckOrigin is nil, the host in the Origin header must not be set or
47
47
// must match the host of the request.
48
48
CheckOrigin func (r * http.Request ) bool
49
+
50
+ // CompressionSupported specify if the server should attempt to negotiate per
51
+ // message compression (RFC 7692). Setting this value to true does not
52
+ // guarantee that compression will be supported. Currently only "no context
53
+ // takeover" modes are supported.
54
+ CompressionSupported bool
49
55
}
50
56
51
57
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
100
106
if r .Method != "GET" {
101
107
return u .returnError (w , r , http .StatusMethodNotAllowed , "websocket: method not GET" )
102
108
}
109
+
110
+ if _ , ok := responseHeader ["Sec-Websocket-Extensions" ]; ok {
111
+ return u .returnError (w , r , http .StatusInternalServerError , "websocket: application specific Sec-Websocket-Extensions headers are unsupported" )
112
+ }
113
+
103
114
if ! tokenListContainsValue (r .Header , "Sec-Websocket-Version" , "13" ) {
104
115
return u .returnError (w , r , http .StatusBadRequest , "websocket: version != 13" )
105
116
}
@@ -127,6 +138,18 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
127
138
128
139
subprotocol := u .selectSubprotocol (r , responseHeader )
129
140
141
+ // Negotiate PMCE
142
+ var compress bool
143
+ if u .CompressionSupported {
144
+ for _ , ext := range parseExtensions (r .Header ) {
145
+ if ext ["" ] != "permessage-deflate" {
146
+ continue
147
+ }
148
+ compress = true
149
+ break
150
+ }
151
+ }
152
+
130
153
var (
131
154
netConn net.Conn
132
155
br * bufio.Reader
@@ -152,6 +175,11 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
152
175
c := newConn (netConn , true , u .ReadBufferSize , u .WriteBufferSize )
153
176
c .subprotocol = subprotocol
154
177
178
+ if compress {
179
+ c .newCompressionWriter = compressNoContextTakeover
180
+ c .newDecompressionReader = decompressNoContextTakeover
181
+ }
182
+
155
183
p := c .writeBuf [:0 ]
156
184
p = append (p , "HTTP/1.1 101 Switching Protocols\r \n Upgrade: websocket\r \n Connection: Upgrade\r \n Sec-WebSocket-Accept: " ... )
157
185
p = append (p , computeAcceptKey (challengeKey )... )
@@ -161,6 +189,9 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
161
189
p = append (p , c .subprotocol ... )
162
190
p = append (p , "\r \n " ... )
163
191
}
192
+ if compress {
193
+ p = append (p , "Sec-Websocket-Extensions: permessage-deflate; server_no_context_takeover; client_no_context_takeover\r \n " ... )
194
+ }
164
195
for k , vs := range responseHeader {
165
196
if k == "Sec-Websocket-Protocol" {
166
197
continue
0 commit comments