Implementing permessage-deflate in WebSockets

user1491657 picture user1491657 · May 20, 2015 · Viewed 10.4k times · Source

I hava a problem understanding and implementing a permessage-deflate extension in WebSockets.

So far, I have added 'Sec-WebSocket-Extensions: permessage-deflate' inside handshake code. It seems to work all fine.

However when I send a "TEST" message from the server (Node.js) to the Client (JS), it seems that the browser (both Chrome and Firefox) is not decompressing the data itself.

How to properly implement data compression and decompression using permessage-deflate extension?

Request Header:

GET ws://localhost/ HTTP/1.1
Host: localhost
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Origin: null
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: nl-NL,nl;q=0.8,en-US;q=0.6,en;q=0.4
Sec-WebSocket-Key: X3RofjiYbzVR8zUPI5ZI6w==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Protocol: Exodus_101

Response Header:

HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
sec-websocket-accept: sFO1Id30BZe63QWcm894hnnb+Pg=
Sec-WebSocket-Protocol: Exodus_101
Sec-WebSocket-Extensions: permessage-deflate

Answer

Kaushik Wavhal picture Kaushik Wavhal · Nov 18, 2016

Both, the server and the client compresses the payload data portion of WebSocket data messages on a per-message basis using parameters negotiated during the opening handshake

permessage-deflate header is used in the handshake to indicate whether a connection should use compression.

  1. When a client sends a websocket request, it send's permessage-deflate in the websocket extensions header IF the client browser supports it. The server knows if a client supports compression based on this header.
  2. If the server decides to use compression, it responds with the same header similar to an ACK message. The client after receiving the response decides whether or not to compress the data based on the server's response.

Once both the sever and the client decides to use compression, they individually have to compress the message using deflate compression technique. i.e You'll have to enable compression on the server by using the "perMessageDeflate" option while creating the websocket server. the ws node module enables this by default. The ws module takes care of the header flags so that you don't need to implicitly set it.

Note: Deflate uses a combination of LZ77 and Huffman coding to compress data.The client_max_window_bits; server_max_window_bits=10 header flags are used to set a custom buffer/'sliding window' used by the LZ77 algorithm to decrease memory overhead.