From dacac60eadf24f5ca9d434eb54ce9dbc2cc0becc Mon Sep 17 00:00:00 2001
From: Jared Newman <jnewman2501@gmail.com>
Date: Thu, 21 Feb 2019 15:58:15 -0800
Subject: [PATCH] Add NotContentTypes option

---
 gzip.go | 50 ++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 46 insertions(+), 4 deletions(-)

diff --git a/gzip.go b/gzip.go
index c112bbd..ae74e8c 100644
--- a/gzip.go
+++ b/gzip.go
@@ -348,6 +348,7 @@ func GzipHandlerWithOpts(opts ...option) (func(http.Handler) http.Handler, error
 // Parsed representation of one of the inputs to ContentTypes.
 // See https://golang.org/pkg/mime/#ParseMediaType
 type parsedContentType struct {
+	not       bool
 	mediaType string
 	params    map[string]string
 }
@@ -431,7 +432,44 @@ func ContentTypes(types []string) option {
 		for _, v := range types {
 			mediaType, params, err := mime.ParseMediaType(v)
 			if err == nil {
-				c.contentTypes = append(c.contentTypes, parsedContentType{mediaType, params})
+				c.contentTypes = append(c.contentTypes, parsedContentType{
+					mediaType: mediaType,
+					params:    params,
+				})
+			}
+		}
+	}
+}
+
+// ContentTypes specifies a list of content types to compare
+// the Content-Type header to before compressing. If any
+// match, the response will be returned as-is.
+//
+// Content types are compared in a case-insensitive, whitespace-ignored
+// manner.
+//
+// A MIME type without any other directive will match a content type
+// that has the same MIME type, regardless of that content type's other
+// directives. I.e., "text/html" will match both "text/html" and
+// "text/html; charset=utf-8".
+//
+// A MIME type with any other directive will only match a content type
+// that has the same MIME type and other directives. I.e.,
+// "text/html; charset=utf-8" will only match "text/html; charset=utf-8".
+//
+// By default, responses are gzipped regardless of
+// Content-Type.
+func NotContentTypes(types []string) option {
+	return func(c *config) {
+		c.contentTypes = []parsedContentType{}
+		for _, v := range types {
+			mediaType, params, err := mime.ParseMediaType(v)
+			if err == nil {
+				c.contentTypes = append(c.contentTypes, parsedContentType{
+					not:       true,
+					mediaType: mediaType,
+					params:    params,
+				})
 			}
 		}
 	}
@@ -464,13 +502,17 @@ func handleContentType(contentTypes []parsedContentType, ct string) bool {
 		return false
 	}
 
+	var match = false
 	for _, c := range contentTypes {
-		if c.equals(mediaType, params) {
-			return true
+		if c.equals(mediaType, params) && !c.not {
+			match = true
+		} else if c.equals(mediaType, params) && c.not {
+			match = false
+			break
 		}
 	}
 
-	return false
+	return match
 }
 
 // parseEncodings attempts to parse a list of codings, per RFC 2616, as might