internal/httpd/compress_test.go

v1.33.0
gitbay/internal/httpd/compress_test.go history · blame · raw

81 lines · 2989 bytes

 1package httpd
 2
 3import (
 4	"bytes"
 5	"compress/gzip"
 6	"io"
 7	"net/http"
 8	"net/http/httptest"
 9	"testing"
10
11	"gitbay.org/gitbay/internal/config"
12)
13
14func plainServer() *Server {
15	cfg := config.Default()
16	cfg.Server.SiteURL = "https://forge.test/"
17	return &Server{cfg: cfg}
18}
19
20func get(t *testing.T, h http.Handler, path string, hdr map[string]string) *httptest.ResponseRecorder {
21	t.Helper()
22	r := httptest.NewRequest("GET", path, nil)
23	r.Host = "forge.test"
24	for k, v := range hdr {
25		r.Header.Set(k, v)
26	}
27	w := httptest.NewRecorder()
28	h.ServeHTTP(w, r)
29	return w
30}
31
32// The stylesheet is gzipped for a client that accepts it and served as-is
33// for one that does not; both bodies are the same bytes (#232).
34func TestStylesheetIsCompressed(t *testing.T) {
35	h := plainServer().Handler()
36	plain := get(t, h, "/static/style.css", nil)
37	if plain.Code != 200 || plain.Header().Get("Content-Encoding") != "" {
38		t.Fatalf("identity: %d %q", plain.Code, plain.Header().Get("Content-Encoding"))
39	}
40	zipped := get(t, h, "/static/style.css", map[string]string{"Accept-Encoding": "gzip, br"})
41	if zipped.Code != 200 || zipped.Header().Get("Content-Encoding") != "gzip" || zipped.Header().Get("Vary") != "Accept-Encoding" {
42		t.Fatalf("gzip: %d %q vary=%q", zipped.Code, zipped.Header().Get("Content-Encoding"), zipped.Header().Get("Vary"))
43	}
44	if zipped.Body.Len() >= plain.Body.Len()/2 {
45		t.Fatalf("gzip body %d bytes, plain %d", zipped.Body.Len(), plain.Body.Len())
46	}
47	zr, err := gzip.NewReader(zipped.Body)
48	if err != nil {
49		t.Fatal(err)
50	}
51	body, _ := io.ReadAll(zr)
52	if !bytes.Equal(body, plain.Body.Bytes()) {
53		t.Fatal("gunzipped body differs from the identity body")
54	}
55	if zipped.Header().Get("ETag") != plain.Header().Get("ETag") {
56		t.Fatal("ETag changed with encoding")
57	}
58	// A 304 carries no body to compress and no encoding header.
59	notMod := get(t, h, "/static/style.css", map[string]string{"Accept-Encoding": "gzip", "If-None-Match": plain.Header().Get("ETag")})
60	if notMod.Code != 304 || notMod.Header().Get("Content-Encoding") != "" {
61		t.Fatalf("304: %d %q", notMod.Code, notMod.Header().Get("Content-Encoding"))
62	}
63}
64
65// A binary type is not touched: the font route keeps its bytes and no
66// encoding header.
67func TestBinaryResponsesPassThrough(t *testing.T) {
68	h := plainServer().Handler()
69	w := get(t, h, "/favicon.svg", map[string]string{"Accept-Encoding": "gzip"})
70	if w.Code != 200 || w.Header().Get("Content-Encoding") != "gzip" {
71		t.Fatalf("svg is text and should gzip: %d %q", w.Code, w.Header().Get("Content-Encoding"))
72	}
73	rec := httptest.NewRecorder()
74	compressed(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
75		w.Header().Set("Content-Type", "application/x-git-upload-pack-result")
76		w.Write([]byte("0000"))
77	})).ServeHTTP(rec, httptest.NewRequest("POST", "/x", nil))
78	if rec.Header().Get("Content-Encoding") != "" || rec.Body.String() != "0000" {
79		t.Fatalf("git transport touched: %q %q", rec.Header().Get("Content-Encoding"), rec.Body.String())
80	}
81}