Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

Compress hosted site responses too

a76b2f38cb6692f7fe88c83e4552205d398f30df · Keenan Nemetz · 12d ago · parent 306f36fc

Compress hosted site responses too

The gzip middleware covered the forge UI and nothing else: server.Handler
dispatches a site host to server/pages before the forge middleware runs, so
every hosted site was serving raw HTML, CSS and JavaScript. A site is a static
file server, which is the best case gzip has.

The compressor moves from server/web to internal/compress so both surfaces share
one implementation of the negotiation and header rules, with two entry points:
New for the forge, which needs the writer inside its own status recorder and
panic handling, and Handler for the site dispatcher.

Site responses keep their ETag and Last-Modified, so revalidation is still a 304
off the blob sha; Vary: Accept-Encoding names the representation; a 304 and a
301 carry no body to compress; and a client that does not ask for gzip still
gets the exact bytes and the exact Content-Length.

Measured on the site path, an HTML page with repeated markup goes from 1.5 KB to
83 bytes.

server/web/auth.go +4−1

@@ -28,6 +28,7 @@ import (
28 28 "github.com/rodent-software/vole/forge/config"
29 29 "github.com/rodent-software/vole/forge/identity"
30 30 "github.com/rodent-software/vole/forge/session"
31 "github.com/rodent-software/vole/internal/compress"
31 32 )
32 33
33 34 const (
@@ -159,7 +160,9 @@ func (w *Web) Middleware(next http.Handler) http.Handler {
159 160 }
160 161 }
161 162 sw := &statusWriter{ResponseWriter: rw}
162 gw := newCompressor(sw, r)
163 // gzip is per request: the status recorder under it is what records the
164 // status and the page-view metric, and the compressor only shapes bytes.
165 gw := compress.New(sw, r)
163 166 defer func() {
164 167 v := recover()
165 168 if v == nil {