diff --git a/go.mod b/go.mod index 395990b..e3a4e30 100644 --- a/go.mod +++ b/go.mod @@ -50,6 +50,7 @@ require ( github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect github.com/aws/aws-sdk-go v1.44.314 // indirect github.com/aws/aws-sdk-go-v2 v1.20.0 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.11 // indirect diff --git a/go.sum b/go.sum index 9f5b813..ad3070b 100644 --- a/go.sum +++ b/go.sum @@ -147,6 +147,8 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/arrow/go/arrow v0.0.0-20210818145353-234c94e4ce64/go.mod h1:2qMFB56yOP3KzkB3PbYZ4AlUFg3a88F67TIx5lB/WwY= github.com/apache/arrow/go/arrow v0.0.0-20211013220434-5962184e7a30/go.mod h1:Q7yQnSMnLvcXlZ8RV+jwz/6y1rQTqbX6C82SndT52Zs= diff --git a/internal/handler/site/middleware/compression.go b/internal/handler/site/middleware/compression.go new file mode 100644 index 0000000..ef3fe97 --- /dev/null +++ b/internal/handler/site/middleware/compression.go @@ -0,0 +1,22 @@ +package middleware + +import ( + "io" + "net/http" + + "github.com/andybalholm/brotli" + "github.com/go-chi/chi/v5/middleware" + "github.com/oursky/pageship/internal/site" +) + +func Compression(next http.Handler) http.Handler { + c := middleware.NewCompressor(5) + c.SetEncoder("br", func(w io.Writer, level int) io.Writer { + return brotli.NewWriterV2(w, level) + }) + return c.Handler(next) +} + +func compression(site *site.Descriptor, next http.Handler) http.Handler { + return Compression(next) +} diff --git a/internal/handler/site/middleware/compression_test.go b/internal/handler/site/middleware/compression_test.go new file mode 100644 index 0000000..6b06fb6 --- /dev/null +++ b/internal/handler/site/middleware/compression_test.go @@ -0,0 +1,69 @@ +package middleware_test + +import ( + "io" + "net/http" + "net/http/httptest" + "testing" + "compress/gzip" + + "github.com/oursky/pageship/internal/handler/site/middleware" + "github.com/stretchr/testify/assert" + "github.com/andybalholm/brotli" +) + +type mockHandler struct { + executeCount int +} + +func (mh *mockHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + mh.executeCount++ + w.Header().Add("Content-Type", "text/plain") + w.Write([]byte("hello")) +} + +func TestCacheGzip(t *testing.T) { + //Setup + h := middleware.Compression(new(mockHandler)) + + //Act Assert + req, err := http.NewRequest("GET", "endpoint", nil) + assert.Empty(t, err) + req.Header.Add("Accept-Encoding", "gzip") + + rec := httptest.NewRecorder() + h.ServeHTTP(rec, req) + + resp := rec.Result() + assert.Equal(t, "gzip", resp.Header.Get("Content-Encoding")) + + gzreader, err := gzip.NewReader(resp.Body) + defer gzreader.Close() + b, err := io.ReadAll(gzreader) + + assert.Empty(t, err) + assert.Equal(t, "hello", string(b)) +} + +func TestCacheBrotli(t *testing.T) { + //Setup + h := middleware.Compression(new(mockHandler)) + + //Act Assert + req, err := http.NewRequest("GET", "endpoint", nil) + assert.Empty(t, err) + req.Header.Add("Accept-Encoding", "br") + + rec := httptest.NewRecorder() + h.ServeHTTP(rec, req) + + resp := rec.Result() + assert.Equal(t, "br", resp.Header.Get("Content-Encoding")) + + brreader := brotli.NewReader(resp.Body) + defer resp.Body.Close() + b, err := io.ReadAll(brreader) + + assert.Empty(t, err) + assert.Equal(t, "hello", string(b)) +} diff --git a/internal/handler/site/middleware/middleware.go b/internal/handler/site/middleware/middleware.go index 99e87f9..80e434d 100644 --- a/internal/handler/site/middleware/middleware.go +++ b/internal/handler/site/middleware/middleware.go @@ -1,10 +1,13 @@ package middleware -import "github.com/oursky/pageship/internal/handler/site" +import ( + "github.com/oursky/pageship/internal/handler/site" +) var Default = []site.Middleware{ RedirectCustomDomain, CanonicalizePath, RouteSPA, IndexPage, + compression, }