From 11a40b50518daa7007ee56f9bc979b079b8fa87a Mon Sep 17 00:00:00 2001 From: Andrew Gaul Date: Sat, 14 Jan 2017 15:20:14 -0800 Subject: [PATCH] Honor Accept-Encoding header in gzip transcoder This avoids sending compressed data to clients which do not support it. --- proxy/proxy.go | 8 ++++---- transcoder/gif.go | 3 ++- transcoder/gzip.go | 17 ++++++++++++++--- transcoder/identity.go | 3 ++- transcoder/jpeg.go | 3 ++- transcoder/minify.go | 3 ++- transcoder/png.go | 3 ++- 7 files changed, 28 insertions(+), 12 deletions(-) diff --git a/proxy/proxy.go b/proxy/proxy.go index bef25a1..6912460 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -16,7 +16,7 @@ type Proxy struct { } type Transcoder interface { - Transcode(*ResponseWriter, *ResponseReader) error + Transcode(*ResponseWriter, *ResponseReader, http.Header) error } func New() *Proxy { @@ -68,7 +68,7 @@ func (p *Proxy) handle(w http.ResponseWriter, r *http.Request) error { defer resp.Body.Close() rw := newResponseWriter(w) rr := newResponseReader(resp) - err = p.proxyResponse(rw, rr) + err = p.proxyResponse(rw, rr, r.Header) read := rr.counter.Count() written := rw.rw.Count() log.Printf("transcoded: %d -> %d (%3.1f%%)", read, written, float64(written)/float64(read)*100) @@ -92,14 +92,14 @@ func forward(r *http.Request) (*http.Response, error) { return http.DefaultTransport.RoundTrip(r) } -func (p *Proxy) proxyResponse(w *ResponseWriter, r *ResponseReader) error { +func (p *Proxy) proxyResponse(w *ResponseWriter, r *ResponseReader, headers http.Header) error { w.takeHeaders(r) transcoder, found := p.transcoders[r.ContentType()] if !found { return w.ReadFrom(r) } w.setChunked() - if err := transcoder.Transcode(w, r); err != nil { + if err := transcoder.Transcode(w, r, headers); err != nil { return fmt.Errorf("transcoding error: %s", err) } return nil diff --git a/transcoder/gif.go b/transcoder/gif.go index db0f2b9..eb0392d 100644 --- a/transcoder/gif.go +++ b/transcoder/gif.go @@ -3,11 +3,12 @@ package transcoder import ( "github.com/barnacs/compy/proxy" "image/gif" + "net/http" ) type Gif struct{} -func (t *Gif) Transcode(w *proxy.ResponseWriter, r *proxy.ResponseReader) error { +func (t *Gif) Transcode(w *proxy.ResponseWriter, r *proxy.ResponseReader, headers http.Header) error { img, err := gif.Decode(r) if err != nil { return err diff --git a/transcoder/gzip.go b/transcoder/gzip.go index 550f2f4..0017aaf 100644 --- a/transcoder/gzip.go +++ b/transcoder/gzip.go @@ -3,6 +3,8 @@ package transcoder import ( "compress/gzip" "github.com/barnacs/compy/proxy" + "net/http" + "strings" ) type Gzip struct { @@ -10,7 +12,7 @@ type Gzip struct { SkipGzipped bool } -func (t *Gzip) Transcode(w *proxy.ResponseWriter, r *proxy.ResponseReader) error { +func (t *Gzip) Transcode(w *proxy.ResponseWriter, r *proxy.ResponseReader, headers http.Header) error { if t.decompress(r) { gzr, err := gzip.NewReader(r.Reader) if err != nil { @@ -21,13 +23,22 @@ func (t *Gzip) Transcode(w *proxy.ResponseWriter, r *proxy.ResponseReader) error r.Header().Del("Content-Encoding") w.Header().Del("Content-Encoding") } - if compress(r) { + + shouldGzip := false + for _, v := range strings.Split(headers.Get("Accept-Encoding"), ", ") { + if strings.SplitN(v, ";", 2)[0] == "gzip" { + shouldGzip = true + break + } + } + + if shouldGzip && compress(r) { gzw := gzip.NewWriter(w.Writer) defer gzw.Flush() w.Writer = gzw w.Header().Set("Content-Encoding", "gzip") } - return t.Transcoder.Transcode(w, r) + return t.Transcoder.Transcode(w, r, headers) } func (t *Gzip) decompress(r *proxy.ResponseReader) bool { diff --git a/transcoder/identity.go b/transcoder/identity.go index b947954..1b957a3 100644 --- a/transcoder/identity.go +++ b/transcoder/identity.go @@ -2,10 +2,11 @@ package transcoder import ( "github.com/barnacs/compy/proxy" + "net/http" ) type Identity struct{} -func (i *Identity) Transcode(w *proxy.ResponseWriter, r *proxy.ResponseReader) error { +func (i *Identity) Transcode(w *proxy.ResponseWriter, r *proxy.ResponseReader, headers http.Header) error { return w.ReadFrom(r) } diff --git a/transcoder/jpeg.go b/transcoder/jpeg.go index 5366788..1ae17f8 100644 --- a/transcoder/jpeg.go +++ b/transcoder/jpeg.go @@ -3,6 +3,7 @@ package transcoder import ( "github.com/barnacs/compy/proxy" "github.com/pixiv/go-libjpeg/jpeg" + "net/http" ) type Jpeg struct { @@ -20,7 +21,7 @@ func NewJpeg(quality int) *Jpeg { } } -func (t *Jpeg) Transcode(w *proxy.ResponseWriter, r *proxy.ResponseReader) error { +func (t *Jpeg) Transcode(w *proxy.ResponseWriter, r *proxy.ResponseReader, headers http.Header) error { img, err := jpeg.Decode(r, t.decOptions) if err != nil { return err diff --git a/transcoder/minify.go b/transcoder/minify.go index 7b91290..78809ed 100644 --- a/transcoder/minify.go +++ b/transcoder/minify.go @@ -6,6 +6,7 @@ import ( "github.com/tdewolff/minify/css" "github.com/tdewolff/minify/html" "github.com/tdewolff/minify/js" + "net/http" ) type Minifier struct { @@ -24,6 +25,6 @@ func NewMinifier() *Minifier { } } -func (t *Minifier) Transcode(w *proxy.ResponseWriter, r *proxy.ResponseReader) error { +func (t *Minifier) Transcode(w *proxy.ResponseWriter, r *proxy.ResponseReader, headers http.Header) error { return t.m.Minify(r.ContentType(), w, r) } diff --git a/transcoder/png.go b/transcoder/png.go index 7249076..fae0e83 100644 --- a/transcoder/png.go +++ b/transcoder/png.go @@ -3,11 +3,12 @@ package transcoder import ( "github.com/barnacs/compy/proxy" "image/png" + "net/http" ) type Png struct{} -func (t *Png) Transcode(w *proxy.ResponseWriter, r *proxy.ResponseReader) error { +func (t *Png) Transcode(w *proxy.ResponseWriter, r *proxy.ResponseReader, headers http.Header) error { img, err := png.Decode(r) if err != nil { return err