@@ -249,34 +249,45 @@ type DialOptions struct {
249249 // Compression sets the compression options.
250250 // By default, compression is disabled.
251251 // See docs on the CompressionOptions type.
252- Compression CompressionOptions
252+ Compression * CompressionOptions
253253}
254254
255255// CompressionOptions describes the available compression options.
256256//
257257// See https://tools.ietf.org/html/rfc7692
258258//
259- // Enabling compression may spike memory usage as each flate.Writer takes up 1.2 MB.
259+ // The NoContextTakeover variables control whether a flate.Writer or flate.Reader is allocated
260+ // for every connection (context takeover) versus shared from a pool (no context takeover).
261+ //
262+ // The advantage to context takeover is more efficient compression as the sliding window from previous
263+ // messages will be used instead of being reset between every message.
264+ //
265+ // The advantage to no context takeover is that the flate structures are allocated as needed
266+ // and shared between connections instead of giving each connection a fixed flate.Writer and
267+ // flate.Reader.
268+ //
269+ // See https://www.igvita.com/2013/11/27/configuring-and-optimizing-websocket-compression.
270+ //
271+ // Enabling compression will increase memory and CPU usage.
272+ // Thus it is not ideal for every use case and disabled by default.
260273// See https://github.com/gorilla/websocket/issues/203
261- // Benchmark before enabling in production.
274+ // Profile before enabling in production.
262275//
263276// This API is experimental and subject to change.
264277type CompressionOptions struct {
265- // ContextTakeover controls whether context takeover is enabled.
266- //
267- // If ContextTakeover == false, then a flate.Writer will be grabbed
268- // from the pool as needed for every message written to the connection.
278+ // ServerNoContextTakeover controls whether the server should use context takeover.
279+ // See docs on CompressionOptions for discussion regarding context takeover.
269280 //
270- // If ContextTakeover == true, then a flate.Writer will be allocated for each connection .
271- // This allows more efficient compression as the sliding window from previous
272- // messages will be used instead of resetting in between every message.
273- // The downside is that for every connection there will be a fixed allocation
274- // for the flate.Writer .
281+ // If set by the client, will guarantee that the server does not use context takeover .
282+ ServerNoContextTakeover bool
283+
284+ // ClientNoContextTakeover controls whether the client should use context takeover.
285+ // See docs on CompressionOptions for discussion regarding context takeover .
275286 //
276- // See https://www.igvita.com/2013/11/27/configuring-and-optimizing-websocket-compression .
277- ContextTakeover bool
287+ // If set by the server, will guarantee that the client does not use context takeover .
288+ ClientNoContextTakeover bool
278289
279- // Level controls the compression level negotiated .
290+ // Level controls the compression level used .
280291 // Defaults to flate.BestSpeed.
281292 Level int
282293
@@ -355,6 +366,9 @@ func dial(ctx context.Context, u string, opts *DialOptions) (_ *Conn, _ *http.Re
355366 if len (opts .Subprotocols ) > 0 {
356367 req .Header .Set ("Sec-WebSocket-Protocol" , strings .Join (opts .Subprotocols , "," ))
357368 }
369+ if opts .Compression != nil {
370+ req .Header .Set ("Sec-WebSocket-Extensions" , "permessage-deflate; server_no_context_takeover; client_no_context_takeover" )
371+ }
358372
359373 resp , err := opts .HTTPClient .Do (req )
360374 if err != nil {
0 commit comments