package hws_test import ( "bytes" "compress/gzip" "io" "net/http" "net/http/httptest" "testing" "git.haelnorr.com/h/golib/hlog" "git.haelnorr.com/h/golib/hws" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func Test_GZIP_Compression(t *testing.T) { var buf bytes.Buffer t.Run("GZIP enabled compresses response", func(t *testing.T) { server, err := hws.NewServer(&hws.Config{ Host: "127.0.0.1", Port: randomPort(), GZIP: true, }) require.NoError(t, err) logger, err := hlog.NewLogger(hlog.LogLevel("Debug"), &buf, nil, "") require.NoError(t, err) err = server.AddLogger(logger) require.NoError(t, err) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) w.Write([]byte("This is a test response that should be compressed")) }) err = server.AddRoutes(hws.Route{ Path: "/test", Method: hws.MethodGET, Handler: handler, }) require.NoError(t, err) err = server.Start(t.Context()) require.NoError(t, err) defer server.Shutdown(t.Context()) <-server.Ready() // Make request with Accept-Encoding: gzip client := &http.Client{} req, err := http.NewRequest("GET", "http://"+server.Addr()+"/test", nil) require.NoError(t, err) req.Header.Set("Accept-Encoding", "gzip") resp, err := client.Do(req) require.NoError(t, err) defer resp.Body.Close() // Verify the response is gzip compressed assert.Equal(t, "gzip", resp.Header.Get("Content-Encoding")) // Decompress and verify content gzReader, err := gzip.NewReader(resp.Body) require.NoError(t, err) defer gzReader.Close() decompressed, err := io.ReadAll(gzReader) require.NoError(t, err) assert.Equal(t, "This is a test response that should be compressed", string(decompressed)) }) t.Run("GZIP disabled does not compress", func(t *testing.T) { server, err := hws.NewServer(&hws.Config{ Host: "127.0.0.1", Port: randomPort(), GZIP: false, }) require.NoError(t, err) logger, err := hlog.NewLogger(hlog.LogLevel("Debug"), &buf, nil, "") require.NoError(t, err) err = server.AddLogger(logger) require.NoError(t, err) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) w.Write([]byte("This response should not be compressed")) }) err = server.AddRoutes(hws.Route{ Path: "/test", Method: hws.MethodGET, Handler: handler, }) require.NoError(t, err) err = server.Start(t.Context()) require.NoError(t, err) defer server.Shutdown(t.Context()) <-server.Ready() // Make request with Accept-Encoding: gzip client := &http.Client{} req, err := http.NewRequest("GET", "http://"+server.Addr()+"/test", nil) require.NoError(t, err) req.Header.Set("Accept-Encoding", "gzip") resp, err := client.Do(req) require.NoError(t, err) defer resp.Body.Close() // Verify the response is NOT gzip compressed assert.Empty(t, resp.Header.Get("Content-Encoding")) // Read plain content body, err := io.ReadAll(resp.Body) require.NoError(t, err) assert.Equal(t, "This response should not be compressed", string(body)) }) t.Run("GZIP not used when client doesn't accept it", func(t *testing.T) { server, err := hws.NewServer(&hws.Config{ Host: "127.0.0.1", Port: randomPort(), GZIP: true, }) require.NoError(t, err) logger, err := hlog.NewLogger(hlog.LogLevel("Debug"), &buf, nil, "") require.NoError(t, err) err = server.AddLogger(logger) require.NoError(t, err) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) w.Write([]byte("plain text")) }) err = server.AddRoutes(hws.Route{ Path: "/test", Method: hws.MethodGET, Handler: handler, }) require.NoError(t, err) err = server.Start(t.Context()) require.NoError(t, err) defer server.Shutdown(t.Context()) <-server.Ready() // Request without Accept-Encoding header should not be compressed client := &http.Client{} req, err := http.NewRequest("GET", "http://"+server.Addr()+"/test", nil) require.NoError(t, err) // Explicitly NOT setting Accept-Encoding header resp, err := client.Do(req) require.NoError(t, err) defer resp.Body.Close() // Verify the response is NOT gzip compressed even though server has GZIP enabled assert.Empty(t, resp.Header.Get("Content-Encoding")) // Read plain content body, err := io.ReadAll(resp.Body) require.NoError(t, err) assert.Equal(t, "plain text", string(body)) }) } func Test_GzipResponseWriter(t *testing.T) { t.Run("Can write through gzip writer", func(t *testing.T) { var buf bytes.Buffer gzWriter := gzip.NewWriter(&buf) testData := []byte("Test data to compress") n, err := gzWriter.Write(testData) require.NoError(t, err) assert.Equal(t, len(testData), n) err = gzWriter.Close() require.NoError(t, err) // Decompress and verify gzReader, err := gzip.NewReader(&buf) require.NoError(t, err) defer gzReader.Close() decompressed, err := io.ReadAll(gzReader) require.NoError(t, err) assert.Equal(t, testData, decompressed) }) t.Run("Headers are set correctly", func(t *testing.T) { handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("test")) }) // Create a simple middleware to test gzip behavior testMiddleware := func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { r.Header.Set("Accept-Encoding", "gzip") next.ServeHTTP(w, r) }) } wrapped := testMiddleware(handler) req := httptest.NewRequest("GET", "/test", nil) req.Header.Set("Accept-Encoding", "gzip") rr := httptest.NewRecorder() wrapped.ServeHTTP(rr, req) // Note: This is a simplified test }) }