package proxy import ( "errors" "net/http" "net/http/httptest" "strconv" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestCacheControl_MiddlewareDefault(t *testing.T) { req := httptest.NewRequest("GET", "/file.html", nil) w := httptest.NewRecorder() h := NewCacheControl(time.Hour).Middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("something")) })) h.ServeHTTP(w, req) resp := w.Result() assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, "public, max-age=3600", resp.Header.Get("Cache-Control")) } func TestCacheControl_MiddlewareDisabled(t *testing.T) { req := httptest.NewRequest("GET", "/file.html", nil) w := httptest.NewRecorder() h := NewCacheControl(0).Middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("something")) })) h.ServeHTTP(w, req) resp := w.Result() assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, "", resp.Header.Get("Cache-Control")) } func TestCacheControl_MiddlewareMime(t *testing.T) { cc := NewCacheControl(time.Hour) cc.AddMime("text/html", time.Hour*2) cc.AddMime("image/png", time.Hour*10) h := cc.Middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("something")) })) { req := httptest.NewRequest("GET", "/file.html", nil) w := httptest.NewRecorder() h.ServeHTTP(w, req) resp := w.Result() assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, "public, max-age=7200", resp.Header.Get("Cache-Control"), "match on .html") } { req := httptest.NewRequest("GET", "/xyz/file.png?something=blah", nil) w := httptest.NewRecorder() h.ServeHTTP(w, req) resp := w.Result() assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, "public, max-age=36000", resp.Header.Get("Cache-Control"), "match on png") } { req := httptest.NewRequest("GET", "/xyz/file.gif?something=blah", nil) w := httptest.NewRecorder() h.ServeHTTP(w, req) resp := w.Result() assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, "public, max-age=3600", resp.Header.Get("Cache-Control"), "no match, default") } { req := httptest.NewRequest("GET", "/xyz/", nil) w := httptest.NewRecorder() h.ServeHTTP(w, req) resp := w.Result() assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, "public, max-age=7200", resp.Header.Get("Cache-Control"), "match on empty (index)") } } func TestMakeCacheControl(t *testing.T) { tbl := []struct { opts []string defAge time.Duration mimeAges map[string]time.Duration err error }{ {nil, time.Duration(0), nil, nil}, {[]string{"12h"}, 12 * time.Hour, nil, nil}, {[]string{"12d"}, 12 * 24 * time.Hour, nil, nil}, {[]string{"a12d"}, 0, nil, errors.New(`can't parse default cache duration: can't parse "a12d" as duration: strconv.Atoi: parsing "a12": invalid syntax`)}, {[]string{"default:12h"}, 12 * time.Hour, nil, nil}, {[]string{"blah:12h"}, 0, nil, errors.New("first cache duration has to be for the default mime")}, {[]string{"a12nop"}, 0, nil, errors.New(`can't parse default cache duration: time: invalid duration "a12nop"`)}, {[]string{"default:a12badone"}, 0, nil, errors.New(`can't parse default cache duration: time: invalid duration "a12badone"`)}, {[]string{"12h", "text/html:10h", "image/png:6h"}, 12 * time.Hour, map[string]time.Duration{"text/html": 10 * time.Hour, "image/png": 6 * time.Hour}, nil}, {[]string{"12h", "10h", "image/png:6h"}, 0, nil, errors.New(`invalid mime:age entry "10h"`)}, {[]string{"12h", "abc:10zzh", "image/png:6h"}, 0, nil, errors.New(`can't parse cache duration from abc:10zzh: time: unknown unit "zzh" in duration "10zzh"`)}, } for i, tt := range tbl { t.Run(strconv.Itoa(i), func(t *testing.T) { res, err := MakeCacheControl(tt.opts) if tt.err != nil { require.EqualError(t, err, tt.err.Error()) return } require.NoError(t, err) assert.Equal(t, tt.defAge, res.defaultMaxAge) for mime, age := range tt.mimeAges { assert.Equal(t, age, res.maxAges[mime]) } assert.Equal(t, len(tt.mimeAges), len(res.maxAges)) }) } }