@@ -46,6 +46,12 @@ type Upgrader struct {
4646// CheckOrigin is nil, the host in the Origin header must not be set or
4747// must match the host of the request.
4848CheckOrigin 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
4955}
5056
5157func (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
100106if r .Method != "GET" {
101107return u .returnError (w , r , http .StatusMethodNotAllowed , "websocket: method not GET" )
102108}
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+
103114if ! tokenListContainsValue (r .Header , "Sec-Websocket-Version" , "13" ) {
104115return u .returnError (w , r , http .StatusBadRequest , "websocket: version != 13" )
105116}
@@ -127,6 +138,18 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
127138
128139subprotocol := u .selectSubprotocol (r , responseHeader )
129140
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+
130153var (
131154netConn net.Conn
132155br * bufio.Reader
@@ -152,6 +175,11 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
152175c := newConn (netConn , true , u .ReadBufferSize , u .WriteBufferSize )
153176c .subprotocol = subprotocol
154177
178+ if compress {
179+ c .newCompressionWriter = compressNoContextTakeover
180+ c .newDecompressionReader = decompressNoContextTakeover
181+ }
182+
155183p := c .writeBuf [:0 ]
156184p = append (p , "HTTP/1.1 101 Switching Protocols\r \n Upgrade: websocket\r \n Connection: Upgrade\r \n Sec-WebSocket-Accept: " ... )
157185p = append (p , computeAcceptKey (challengeKey )... )
@@ -161,6 +189,9 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
161189p = append (p , c .subprotocol ... )
162190p = append (p , "\r \n " ... )
163191}
192+ if compress {
193+ p = append (p , "Sec-Websocket-Extensions: permessage-deflate; server_no_context_takeover; client_no_context_takeover\r \n " ... )
194+ }
164195for k , vs := range responseHeader {
165196if k == "Sec-Websocket-Protocol" {
166197continue
0 commit comments