2017-06-07 01:02:02 +02:00
package middlewares
import (
2017-07-13 17:56:01 +02:00
"io/ioutil"
2017-06-07 01:02:02 +02:00
"net/http"
"net/http/httptest"
"testing"
"github.com/NYTimes/gziphandler"
"github.com/containous/traefik/testhelpers"
"github.com/stretchr/testify/assert"
2017-08-21 11:10:03 +02:00
"github.com/stretchr/testify/require"
2017-08-01 19:32:44 +02:00
"github.com/urfave/negroni"
2017-06-07 01:02:02 +02:00
)
const (
2017-07-13 17:56:01 +02:00
acceptEncodingHeader = "Accept-Encoding"
contentEncodingHeader = "Content-Encoding"
varyHeader = "Vary"
gzipValue = "gzip"
2017-06-07 01:02:02 +02:00
)
func TestShouldCompressWhenNoContentEncodingHeader ( t * testing . T ) {
handler := & Compress { }
req := testhelpers . MustNewRequest ( http . MethodGet , "http://localhost" , nil )
2017-07-13 17:56:01 +02:00
req . Header . Add ( acceptEncodingHeader , gzipValue )
2017-06-07 01:02:02 +02:00
baseBody := generateBytes ( gziphandler . DefaultMinSize )
next := func ( rw http . ResponseWriter , r * http . Request ) {
rw . Write ( baseBody )
}
2017-07-13 17:56:01 +02:00
rw := httptest . NewRecorder ( )
2017-06-07 01:02:02 +02:00
handler . ServeHTTP ( rw , req , next )
2017-07-13 17:56:01 +02:00
assert . Equal ( t , gzipValue , rw . Header ( ) . Get ( contentEncodingHeader ) )
2017-06-07 01:02:02 +02:00
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 )
2017-07-13 17:56:01 +02:00
req . Header . Add ( acceptEncodingHeader , gzipValue )
2017-06-07 01:02:02 +02:00
2017-07-13 17:56:01 +02:00
fakeCompressedBody := generateBytes ( gziphandler . DefaultMinSize )
next := func ( rw http . ResponseWriter , r * http . Request ) {
rw . Header ( ) . Add ( contentEncodingHeader , gzipValue )
rw . Header ( ) . Add ( varyHeader , acceptEncodingHeader )
rw . Write ( fakeCompressedBody )
}
rw := httptest . NewRecorder ( )
handler . ServeHTTP ( rw , req , next )
assert . Equal ( t , gzipValue , rw . Header ( ) . Get ( contentEncodingHeader ) )
assert . Equal ( t , acceptEncodingHeader , rw . Header ( ) . Get ( varyHeader ) )
2017-06-07 01:02:02 +02:00
2017-07-13 17:56:01 +02:00
assert . EqualValues ( t , rw . Body . Bytes ( ) , fakeCompressedBody )
}
func TestShouldNotCompressWhenNoAcceptEncodingHeader ( t * testing . T ) {
handler := & Compress { }
req := testhelpers . MustNewRequest ( http . MethodGet , "http://localhost" , nil )
fakeBody := generateBytes ( gziphandler . DefaultMinSize )
2017-06-07 01:02:02 +02:00
next := func ( rw http . ResponseWriter , r * http . Request ) {
2017-07-13 17:56:01 +02:00
rw . Write ( fakeBody )
2017-06-07 01:02:02 +02:00
}
rw := httptest . NewRecorder ( )
handler . ServeHTTP ( rw , req , next )
2017-07-13 17:56:01 +02:00
assert . Empty ( t , rw . Header ( ) . Get ( contentEncodingHeader ) )
assert . EqualValues ( t , rw . Body . Bytes ( ) , fakeBody )
}
2017-08-21 11:10:03 +02:00
func TestIntegrationShouldNotCompress ( t * testing . T ) {
2017-07-13 17:56:01 +02:00
fakeCompressedBody := generateBytes ( 100000 )
2017-08-21 11:10:03 +02:00
comp := & Compress { }
2017-06-07 01:02:02 +02:00
2017-08-21 11:10:03 +02:00
testCases := [ ] struct {
name string
handler func ( rw http . ResponseWriter , r * http . Request )
expectedStatusCode int
} {
{
name : "when content already compressed" ,
handler : func ( rw http . ResponseWriter , r * http . Request ) {
rw . Header ( ) . Add ( contentEncodingHeader , gzipValue )
rw . Header ( ) . Add ( varyHeader , acceptEncodingHeader )
rw . Write ( fakeCompressedBody )
} ,
expectedStatusCode : http . StatusOK ,
} ,
{
name : "when content already compressed and status code Created" ,
handler : func ( rw http . ResponseWriter , r * http . Request ) {
rw . Header ( ) . Add ( contentEncodingHeader , gzipValue )
rw . Header ( ) . Add ( varyHeader , acceptEncodingHeader )
rw . WriteHeader ( http . StatusCreated )
rw . Write ( fakeCompressedBody )
} ,
expectedStatusCode : http . StatusCreated ,
} ,
2017-07-13 17:56:01 +02:00
}
2017-08-21 11:10:03 +02:00
for _ , test := range testCases {
2017-07-13 17:56:01 +02:00
2017-08-21 11:10:03 +02:00
t . Run ( test . name , func ( t * testing . T ) {
negro := negroni . New ( comp )
negro . UseHandlerFunc ( test . handler )
ts := httptest . NewServer ( negro )
defer ts . Close ( )
2017-07-13 17:56:01 +02:00
2017-08-21 11:10:03 +02:00
req := testhelpers . MustNewRequest ( http . MethodGet , ts . URL , nil )
req . Header . Add ( acceptEncodingHeader , gzipValue )
resp , err := http . DefaultClient . Do ( req )
require . NoError ( t , err )
2017-07-13 17:56:01 +02:00
2017-08-21 11:10:03 +02:00
assert . Equal ( t , test . expectedStatusCode , resp . StatusCode )
2017-07-13 17:56:01 +02:00
2017-08-21 11:10:03 +02:00
assert . Equal ( t , gzipValue , resp . Header . Get ( contentEncodingHeader ) )
assert . Equal ( t , acceptEncodingHeader , resp . Header . Get ( varyHeader ) )
2017-07-13 17:56:01 +02:00
2017-08-21 11:10:03 +02:00
body , err := ioutil . ReadAll ( resp . Body )
require . NoError ( t , err )
assert . EqualValues ( t , fakeCompressedBody , body )
} )
}
2017-07-13 17:56:01 +02:00
}
2017-08-21 11:10:03 +02:00
func TestIntegrationShouldCompress ( t * testing . T ) {
2017-07-13 17:56:01 +02:00
fakeBody := generateBytes ( 100000 )
2017-08-21 11:10:03 +02:00
testCases := [ ] struct {
name string
handler func ( rw http . ResponseWriter , r * http . Request )
expectedStatusCode int
} {
{
name : "when AcceptEncoding header is present" ,
handler : func ( rw http . ResponseWriter , r * http . Request ) {
rw . Write ( fakeBody )
} ,
expectedStatusCode : http . StatusOK ,
} ,
{
name : "when AcceptEncoding header is present and status code Created" ,
handler : func ( rw http . ResponseWriter , r * http . Request ) {
rw . WriteHeader ( http . StatusCreated )
rw . Write ( fakeBody )
} ,
expectedStatusCode : http . StatusCreated ,
} ,
2017-07-13 17:56:01 +02:00
}
2017-08-21 11:10:03 +02:00
for _ , test := range testCases {
2017-07-13 17:56:01 +02:00
2017-08-21 11:10:03 +02:00
t . Run ( test . name , func ( t * testing . T ) {
comp := & Compress { }
2017-07-13 17:56:01 +02:00
2017-08-21 11:10:03 +02:00
negro := negroni . New ( comp )
negro . UseHandlerFunc ( test . handler )
ts := httptest . NewServer ( negro )
defer ts . Close ( )
req := testhelpers . MustNewRequest ( http . MethodGet , ts . URL , nil )
req . Header . Add ( acceptEncodingHeader , gzipValue )
resp , err := http . DefaultClient . Do ( req )
require . NoError ( t , err )
2017-07-13 17:56:01 +02:00
2017-08-21 11:10:03 +02:00
assert . Equal ( t , test . expectedStatusCode , resp . StatusCode )
2017-07-13 17:56:01 +02:00
2017-08-21 11:10:03 +02:00
assert . Equal ( t , gzipValue , resp . Header . Get ( contentEncodingHeader ) )
assert . Equal ( t , acceptEncodingHeader , resp . Header . Get ( varyHeader ) )
2017-07-13 17:56:01 +02:00
2017-08-21 11:10:03 +02:00
body , err := ioutil . ReadAll ( resp . Body )
require . NoError ( t , err )
if assert . ObjectsAreEqualValues ( body , fakeBody ) {
assert . Fail ( t , "expected a compressed body" , "got %v" , body )
}
} )
2017-07-13 17:56:01 +02:00
}
2017-06-07 01:02:02 +02:00
}
func generateBytes ( len int ) [ ] byte {
var value [ ] byte
for i := 0 ; i < len ; i ++ {
2017-07-13 17:56:01 +02:00
value = append ( value , 0x61 + byte ( i ) )
2017-06-07 01:02:02 +02:00
}
return value
}