From e142e08cbe82354cbee73f4b023623f04a55924d Mon Sep 17 00:00:00 2001
From: Anmol Sethi <hi@nhooyr.io>
Date: Mon, 11 Nov 2019 19:28:39 -0500
Subject: [PATCH] Improve compression docs

---
 README.md    |  8 ++++----
 handshake.go | 44 +++++++++++++++++++++++++++++---------------
 2 files changed, 33 insertions(+), 19 deletions(-)

diff --git a/README.md b/README.md
index c426423..b5adc59 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,9 @@
 # websocket
 
-[![GitHub Release](https://img.shields.io/github/v/release/nhooyr/websocket?color=6b9ded&sort=semver)](https://github.com/nhooyr/websocket/releases)
-[![GoDoc](https://godoc.org/nhooyr.io/websocket?status.svg)](https://godoc.org/nhooyr.io/websocket)
-[![Coveralls](https://img.shields.io/coveralls/github/nhooyr/websocket?color=65d6a4)](https://coveralls.io/github/nhooyr/websocket)
-[![CI Status](https://github.com/nhooyr/websocket/workflows/ci/badge.svg)](https://github.com/nhooyr/websocket/actions)
+[![version](https://img.shields.io/github/v/release/nhooyr/websocket?color=6b9ded&sort=semver)](https://github.com/nhooyr/websocket/releases)
+[![docs](https://godoc.org/nhooyr.io/websocket?status.svg)](https://godoc.org/nhooyr.io/websocket)
+[![coverage](https://img.shields.io/coveralls/github/nhooyr/websocket?color=65d6a4)](https://coveralls.io/github/nhooyr/websocket)
+[![ci](https://github.com/nhooyr/websocket/workflows/ci/badge.svg)](https://github.com/nhooyr/websocket/actions)
 
 websocket is a minimal and idiomatic WebSocket library for Go.
 
diff --git a/handshake.go b/handshake.go
index 81ebf48..2cde6ae 100644
--- a/handshake.go
+++ b/handshake.go
@@ -249,34 +249,45 @@ type DialOptions struct {
 	// Compression sets the compression options.
 	// By default, compression is disabled.
 	// See docs on the CompressionOptions type.
-	Compression CompressionOptions
+	Compression *CompressionOptions
 }
 
 // CompressionOptions describes the available compression options.
 //
 // See https://tools.ietf.org/html/rfc7692
 //
-// Enabling compression may spike memory usage as each flate.Writer takes up 1.2 MB.
+// The NoContextTakeover variables control whether a flate.Writer or flate.Reader is allocated
+// for every connection (context takeover) versus shared from a pool (no context takeover).
+//
+// The advantage to context takeover is more efficient compression as the sliding window from previous
+// messages will be used instead of being reset between every message.
+//
+// The advantage to no context takeover is that the flate structures are allocated as needed
+// and shared between connections instead of giving each connection a fixed flate.Writer and
+// flate.Reader.
+//
+// See https://www.igvita.com/2013/11/27/configuring-and-optimizing-websocket-compression.
+//
+// Enabling compression will increase memory and CPU usage.
+// Thus it is not ideal for every use case and disabled by default.
 // See https://github.com/gorilla/websocket/issues/203
-// Benchmark before enabling in production.
+// Profile before enabling in production.
 //
 // This API is experimental and subject to change.
 type CompressionOptions struct {
-	// ContextTakeover controls whether context takeover is enabled.
-	//
-	// If ContextTakeover == false, then a flate.Writer will be grabbed
-	// from the pool as needed for every message written to the connection.
+	// ServerNoContextTakeover controls whether the server should use context takeover.
+	// See docs on CompressionOptions for discussion regarding context takeover.
 	//
-	// If ContextTakeover == true, then a flate.Writer will be allocated for each connection.
-	// This allows more efficient compression as the sliding window from previous
-	// messages will be used instead of resetting in between every message.
-	// The downside is that for every connection there will be a fixed allocation
-	// for the flate.Writer.
+	// If set by the client, will guarantee that the server does not use context takeover.
+	ServerNoContextTakeover bool
+
+	// ClientNoContextTakeover controls whether the client should use context takeover.
+	// See docs on CompressionOptions for discussion regarding context takeover.
 	//
-	// See https://www.igvita.com/2013/11/27/configuring-and-optimizing-websocket-compression.
-	ContextTakeover bool
+	// If set by the server, will guarantee that the client does not use context takeover.
+	ClientNoContextTakeover bool
 
-	// Level controls the compression level negotiated.
+	// Level controls the compression level used.
 	// Defaults to flate.BestSpeed.
 	Level int
 
@@ -355,6 +366,9 @@ func dial(ctx context.Context, u string, opts *DialOptions) (_ *Conn, _ *http.Re
 	if len(opts.Subprotocols) > 0 {
 		req.Header.Set("Sec-WebSocket-Protocol", strings.Join(opts.Subprotocols, ","))
 	}
+	if opts.Compression != nil {
+		req.Header.Set("Sec-WebSocket-Extensions", "permessage-deflate; server_no_context_takeover; client_no_context_takeover")
+	}
 
 	resp, err := opts.HTTPClient.Do(req)
 	if err != nil {
-- 
GitLab