From 96eab1202717e073782ec399a4e0820cae15b1bb Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Thu, 17 Aug 2017 17:19:06 -0700 Subject: Updating server dependancies. (#7246) --- vendor/github.com/NYTimes/gziphandler/gzip.go | 91 ++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 8 deletions(-) (limited to 'vendor/github.com/NYTimes/gziphandler/gzip.go') diff --git a/vendor/github.com/NYTimes/gziphandler/gzip.go b/vendor/github.com/NYTimes/gziphandler/gzip.go index ea6dba1e7..c47039fd3 100644 --- a/vendor/github.com/NYTimes/gziphandler/gzip.go +++ b/vendor/github.com/NYTimes/gziphandler/gzip.go @@ -80,6 +80,8 @@ type GzipResponseWriter struct { minSize int // Specifed the minimum response size to gzip. If the response length is bigger than this value, it is compressed. buf []byte // Holds the first part of the write before reaching the minSize or the end of the write. + + contentTypes []string // Only compress if the response is one of these content-types. All are accepted if empty. } // Write appends data to the gzip writer. @@ -100,8 +102,10 @@ func (w *GzipResponseWriter) Write(b []byte) (int, error) { // On the first write, w.buf changes from nil to a valid slice w.buf = append(w.buf, b...) - // If the global writes are bigger than the minSize, compression is enable. - if len(w.buf) >= w.minSize { + // If the global writes are bigger than the minSize and we're about to write + // a response containing a content type we want to handle, enable + // compression. + if len(w.buf) >= w.minSize && handleContentType(w.contentTypes, w) { err := w.startGzip() if err != nil { return 0, err @@ -230,14 +234,25 @@ func NewGzipLevelHandler(level int) (func(http.Handler) http.Handler, error) { // NewGzipLevelAndMinSize behave as NewGzipLevelHandler except it let the caller // specify the minimum size before compression. func NewGzipLevelAndMinSize(level, minSize int) (func(http.Handler) http.Handler, error) { - if level != gzip.DefaultCompression && (level < gzip.BestSpeed || level > gzip.BestCompression) { - return nil, fmt.Errorf("invalid compression level requested: %d", level) + return GzipHandlerWithOpts(CompressionLevel(level), MinSize(minSize)) +} + +func GzipHandlerWithOpts(opts ...option) (func(http.Handler) http.Handler, error) { + c := &config{ + level: gzip.DefaultCompression, + minSize: DefaultMinSize, } - if minSize < 0 { - return nil, fmt.Errorf("minimum size must be more than zero") + + for _, o := range opts { + o(c) } + + if err := c.validate(); err != nil { + return nil, err + } + return func(h http.Handler) http.Handler { - index := poolIndex(level) + index := poolIndex(c.level) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Add(vary, acceptEncoding) @@ -246,7 +261,8 @@ func NewGzipLevelAndMinSize(level, minSize int) (func(http.Handler) http.Handler gw := &GzipResponseWriter{ ResponseWriter: w, index: index, - minSize: minSize, + minSize: c.minSize, + contentTypes: c.contentTypes, } defer gw.Close() @@ -258,6 +274,48 @@ func NewGzipLevelAndMinSize(level, minSize int) (func(http.Handler) http.Handler }, nil } +// Used for functional configuration. +type config struct { + minSize int + level int + contentTypes []string +} + +func (c *config) validate() error { + if c.level != gzip.DefaultCompression && (c.level < gzip.BestSpeed || c.level > gzip.BestCompression) { + return fmt.Errorf("invalid compression level requested: %d", c.level) + } + + if c.minSize < 0 { + return fmt.Errorf("minimum size must be more than zero") + } + + return nil +} + +type option func(c *config) + +func MinSize(size int) option { + return func(c *config) { + c.minSize = size + } +} + +func CompressionLevel(level int) option { + return func(c *config) { + c.level = level + } +} + +func ContentTypes(types []string) option { + return func(c *config) { + c.contentTypes = []string{} + for _, v := range types { + c.contentTypes = append(c.contentTypes, strings.ToLower(v)) + } + } +} + // GzipHandler wraps an HTTP handler, to transparently gzip the response body if // the client supports it (via the Accept-Encoding header). This will compress at // the default compression level. @@ -273,6 +331,23 @@ func acceptsGzip(r *http.Request) bool { return acceptedEncodings["gzip"] > 0.0 } +// returns true if we've been configured to compress the specific content type. +func handleContentType(contentTypes []string, w http.ResponseWriter) bool { + // If contentTypes is empty we handle all content types. + if len(contentTypes) == 0 { + return true + } + + ct := strings.ToLower(w.Header().Get(contentType)) + for _, c := range contentTypes { + if c == ct { + return true + } + } + + return false +} + // parseEncodings attempts to parse a list of codings, per RFC 2616, as might // appear in an Accept-Encoding header. It returns a map of content-codings to // quality values, and an error containing the errors encountered. It's probably -- cgit v1.2.3-1-g7c22