diff --git a/middlewares/compress.go b/middlewares/compress.go index d4a07e37c..5df1dd9c9 100644 --- a/middlewares/compress.go +++ b/middlewares/compress.go @@ -6,12 +6,26 @@ import ( "github.com/NYTimes/gziphandler" ) -// Compress is a middleware that allows redirections -type Compress struct { +const ( + contentEncodingHeader = "Content-Encoding" +) + +// Compress is a middleware that allows redirection +type Compress struct{} + +// ServerHTTP is a function used by Negroni +func (c *Compress) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + if isEncoded(r.Header) { + next.ServeHTTP(rw, r) + } else { + newGzipHandler := gziphandler.GzipHandler(next) + newGzipHandler.ServeHTTP(rw, r) + } } -// ServerHTTP is a function used by negroni -func (c *Compress) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { - newGzipHandler := gziphandler.GzipHandler(next) - newGzipHandler.ServeHTTP(rw, r) +func isEncoded(headers http.Header) bool { + header := headers.Get(contentEncodingHeader) + // According to https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding, + // content is not encoded if the header 'Content-Encoding' is empty or equals to 'identity'. + return header != "" && header != "identity" } diff --git a/middlewares/compress_test.go b/middlewares/compress_test.go new file mode 100644 index 000000000..c83bd3b1d --- /dev/null +++ b/middlewares/compress_test.go @@ -0,0 +1,69 @@ +package middlewares + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/NYTimes/gziphandler" + "github.com/containous/traefik/testhelpers" + "github.com/stretchr/testify/assert" +) + +const ( + acceptEncodingHeader = "Accept-Encoding" + varyHeader = "Vary" + gzip = "gzip" +) + +func TestShouldCompressWhenNoContentEncodingHeader(t *testing.T) { + handler := &Compress{} + + req := testhelpers.MustNewRequest(http.MethodGet, "http://localhost", nil) + req.Header.Add(acceptEncodingHeader, gzip) + + baseBody := generateBytes(gziphandler.DefaultMinSize) + next := func(rw http.ResponseWriter, r *http.Request) { + rw.Write(baseBody) + } + rw := httptest.NewRecorder() + + handler.ServeHTTP(rw, req, next) + + assert.Equal(t, gzip, rw.Header().Get(contentEncodingHeader)) + assert.Equal(t, acceptEncodingHeader, rw.Header().Get(varyHeader)) + + if assert.ObjectsAreEqualValues(rw.Body.Bytes(), baseBody) { + assert.Fail(t, "expected a compressed body", "got %v", rw.Body.Bytes()) + } +} + +func TestShouldNotCompressWhenContentEncodingHeader(t *testing.T) { + handler := &Compress{} + + req := testhelpers.MustNewRequest(http.MethodGet, "http://localhost", nil) + req.Header.Add(acceptEncodingHeader, gzip) + req.Header.Add(contentEncodingHeader, gzip) + + baseBody := generateBytes(gziphandler.DefaultMinSize) + + next := func(rw http.ResponseWriter, r *http.Request) { + rw.Write(baseBody) + } + + rw := httptest.NewRecorder() + handler.ServeHTTP(rw, req, next) + + assert.Equal(t, "", rw.Header().Get(contentEncodingHeader)) + assert.Equal(t, "", rw.Header().Get(varyHeader)) + + assert.EqualValues(t, rw.Body.Bytes(), baseBody) +} + +func generateBytes(len int) []byte { + var value []byte + for i := 0; i < len; i++ { + value = append(value, 0x61) + } + return value +} diff --git a/provider/eureka/eureka.go b/provider/eureka/eureka.go index a848280b2..5a1a6c4fd 100644 --- a/provider/eureka/eureka.go +++ b/provider/eureka/eureka.go @@ -8,9 +8,9 @@ import ( "time" "github.com/ArthurHlt/go-eureka-client/eureka" - log "github.com/Sirupsen/logrus" "github.com/cenk/backoff" "github.com/containous/traefik/job" + "github.com/containous/traefik/log" "github.com/containous/traefik/provider" "github.com/containous/traefik/safe" "github.com/containous/traefik/types" diff --git a/provider/marathon/marathon.go b/provider/marathon/marathon.go index cc017a567..1bed45298 100644 --- a/provider/marathon/marathon.go +++ b/provider/marathon/marathon.go @@ -167,13 +167,13 @@ func (p *Provider) loadMarathonConfig() *types.Configuration { applications, err := p.marathonClient.Applications(nil) if err != nil { - log.Errorf("Failed to create a client for marathon, error: %s", err) + log.Errorf("Failed to retrieve applications from Marathon, error: %s", err) return nil } tasks, err := p.marathonClient.AllTasks(&marathon.AllTasksOpts{Status: "running"}) if err != nil { - log.Errorf("Failed to create a client for marathon, error: %s", err) + log.Errorf("Failed to retrieve task from Marathon, error: %s", err) return nil }