internal/httpd/compress_test.go
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}