code.vegaprotocol.io/vega@v0.79.0/core/api/rest/gziphandler_test.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package rest
    17  
    18  import (
    19  	"compress/gzip"
    20  	"context"
    21  	"io/ioutil"
    22  	"net/http"
    23  	"net/http/httptest"
    24  	"net/http/httputil"
    25  	"testing"
    26  
    27  	"code.vegaprotocol.io/vega/logging"
    28  )
    29  
    30  func headerNotPresent(t *testing.T, x *httptest.ResponseRecorder, key string) {
    31  	t.Helper()
    32  	res := x.Result()
    33  	defer res.Body.Close()
    34  	h, found := res.Header[key]
    35  	if found || len(h) > 0 {
    36  		t.Fatalf("Unexpected header: %s", key)
    37  	}
    38  }
    39  
    40  func headerPresent(t *testing.T, x *httptest.ResponseRecorder, key string, expected []string) {
    41  	t.Helper()
    42  	res := x.Result()
    43  	defer res.Body.Close()
    44  	h, found := res.Header[key]
    45  	if !found || len(h) == 0 {
    46  		t.Fatalf("Missing header: %s", key)
    47  	}
    48  	if len(h) != len(expected) {
    49  		t.Fatalf("Unexpected number of headers for \"%s\": expected %d, got %d", key, len(expected), len(h))
    50  	}
    51  	for i := range h {
    52  		if h[i] != expected[i] {
    53  			t.Fatalf("Unexpected header for \"%s\": #%d, expected \"%s\", got \"%s\"", key, i, expected[i], h[i])
    54  		}
    55  	}
    56  }
    57  
    58  func TestNoGzip(t *testing.T) {
    59  	req, err := http.NewRequestWithContext(
    60  		context.Background(), http.MethodGet, "http://example.com/", nil)
    61  	if err != nil {
    62  		t.Fatal(err)
    63  	}
    64  
    65  	logger := logging.NewTestLogger()
    66  	defer logger.Sync()
    67  
    68  	rec := httptest.NewRecorder()
    69  	newGzipHandler(*logger, func(w http.ResponseWriter, r *http.Request) {
    70  		w.Write([]byte("test"))
    71  	})(rec, req)
    72  
    73  	if rec.Code != 200 {
    74  		t.Fatalf("expected 200 got %d", rec.Code)
    75  	}
    76  
    77  	headerNotPresent(t, rec, "Content-Encoding")
    78  
    79  	if rec.Body.String() != "test" {
    80  		t.Fatalf(`expected "test" go "%s"`, rec.Body.String())
    81  	}
    82  
    83  	if testing.Verbose() {
    84  		res := rec.Result()
    85  		defer res.Body.Close()
    86  		b, _ := httputil.DumpResponse(res, true)
    87  		t.Log("\n" + string(b))
    88  	}
    89  }
    90  
    91  func TestGzip(t *testing.T) {
    92  	req, err := http.NewRequestWithContext(
    93  		context.Background(), http.MethodGet, "http://example.com/", nil)
    94  	if err != nil {
    95  		t.Fatal(err)
    96  	}
    97  	req.Header.Set("Accept-Encoding", "gzip, deflate")
    98  
    99  	logger := logging.NewTestLogger()
   100  	defer logger.Sync()
   101  
   102  	rec := httptest.NewRecorder()
   103  	newGzipHandler(*logger, func(w http.ResponseWriter, r *http.Request) {
   104  		w.Header().Set("Content-Length", "4")
   105  		w.Header().Set("Content-Type", "text/test")
   106  		w.Write([]byte("test"))
   107  	})(rec, req)
   108  
   109  	if rec.Code != 200 {
   110  		t.Fatalf("expected 200 got %d", rec.Code)
   111  	}
   112  
   113  	headerPresent(t, rec, "Content-Encoding", []string{"gzip"})
   114  	headerNotPresent(t, rec, "Content-Length")
   115  	headerPresent(t, rec, "Content-Type", []string{"text/test"})
   116  
   117  	r, err := gzip.NewReader(rec.Body)
   118  	if err != nil {
   119  		t.Fatal(err)
   120  	}
   121  
   122  	body, err := ioutil.ReadAll(r)
   123  	if err != nil {
   124  		t.Fatal(err)
   125  	}
   126  
   127  	if string(body) != "test" {
   128  		t.Fatalf(`expected "test" go "%s"`, string(body))
   129  	}
   130  
   131  	if testing.Verbose() {
   132  		res := rec.Result()
   133  		defer res.Body.Close()
   134  		b, _ := httputil.DumpResponse(res, true)
   135  		t.Log("\n" + string(b))
   136  	}
   137  }
   138  
   139  func TestNoBody(t *testing.T) {
   140  	req, err := http.NewRequestWithContext(
   141  		context.Background(), http.MethodGet, "http://example.com/", nil)
   142  	if err != nil {
   143  		t.Fatal(err)
   144  	}
   145  	req.Header.Set("Accept-Encoding", "gzip, deflate")
   146  
   147  	logger := logging.NewTestLogger()
   148  	defer logger.Sync()
   149  
   150  	rec := httptest.NewRecorder()
   151  	newGzipHandler(*logger, func(w http.ResponseWriter, r *http.Request) {
   152  		w.WriteHeader(http.StatusNoContent)
   153  	})(rec, req)
   154  
   155  	if rec.Code != http.StatusNoContent {
   156  		t.Fatalf("expected %d got %d", http.StatusNoContent, rec.Code)
   157  	}
   158  
   159  	headerNotPresent(t, rec, "Content-Encoding")
   160  
   161  	if rec.Body.Len() > 0 {
   162  		t.Logf("%q", rec.Body.String())
   163  		t.Fatalf("no body expected for %d bytes", rec.Body.Len())
   164  	}
   165  
   166  	if testing.Verbose() {
   167  		res := rec.Result()
   168  		defer res.Body.Close()
   169  		b, _ := httputil.DumpResponse(res, true)
   170  		t.Log("\n" + string(b))
   171  	}
   172  }
   173  
   174  func BenchmarkGzip(b *testing.B) {
   175  	body := []byte("testtesttesttesttesttesttesttesttesttesttesttesttest")
   176  
   177  	req, err := http.NewRequest(http.MethodGet, "http://example.com/", nil)
   178  	if err != nil {
   179  		b.Fatal(err)
   180  	}
   181  	req.Header.Set("Accept-Encoding", "gzip, deflate")
   182  
   183  	logger := logging.NewTestLogger()
   184  	defer logger.Sync()
   185  
   186  	b.ResetTimer()
   187  	b.RunParallel(func(pb *testing.PB) {
   188  		for pb.Next() {
   189  			rec := httptest.NewRecorder()
   190  			newGzipHandler(*logger, func(w http.ResponseWriter, r *http.Request) {
   191  				w.Write(body)
   192  			})(rec, req)
   193  
   194  			if rec.Code != http.StatusOK {
   195  				b.Fatalf("expected %d got %d", http.StatusOK, rec.Code)
   196  			}
   197  			if rec.Body.Len() != 49 {
   198  				b.Fatalf("expected 49 bytes, got %d bytes", rec.Body.Len())
   199  			}
   200  		}
   201  	})
   202  }