diff --git a/go.mod b/go.mod index b54bf3c..3e9b5f9 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.25 require ( dario.cat/mergo v1.0.2 + github.com/andybalholm/brotli v1.2.0 github.com/fatih/color v1.18.0 github.com/fsnotify/fsnotify v1.9.0 github.com/gohugoio/hugo v0.149.1 diff --git a/go.sum b/go.sum index 1faf00d..4454c07 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ github.com/BurntSushi/locker v0.0.0-20171006230638-a6e239ea1c69 h1:+tu3HOoMXB7RX github.com/BurntSushi/locker v0.0.0-20171006230638-a6e239ea1c69/go.mod h1:L1AbZdiDllfyYH5l5OkAaZtk7VkWe89bPJFmnDBNHxg= github.com/alecthomas/chroma/v2 v2.20.0 h1:sfIHpxPyR07/Oylvmcai3X/exDlE8+FA820NTz+9sGw= github.com/alecthomas/chroma/v2 v2.20.0/go.mod h1:e7tViK0xh/Nf4BYHl00ycY6rV7b8iXBksI9E359yNmA= +github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ= +github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY= github.com/armon/go-radix v1.0.1-0.20221118154546-54df44f2176c h1:651/eoCRnQ7YtSjAnSzRucrJz+3iGEFt+ysraELS81M= github.com/armon/go-radix v1.0.1-0.20221118154546-54df44f2176c/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= @@ -172,6 +174,8 @@ github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZB github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM= github.com/woodsbury/decimal128 v1.3.0 h1:8pffMNWIlC0O5vbyHWFZAt5yWvWcrHA+3ovIIjVWss0= github.com/woodsbury/decimal128 v1.3.0/go.mod h1:C5UTmyTjW3JftjUFzOVhC20BEQa2a4ZKOB5I6Zjb+ds= +github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= +github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/yuin/goldmark v1.7.13 h1:GPddIs617DnBLFFVJFgpo1aBfe/4xcvMc3SB5t/D0pA= github.com/yuin/goldmark v1.7.13/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= github.com/yuin/goldmark-emoji v1.0.6 h1:QWfF2FYaXwL74tfGOW5izeiZepUDroDJfWubQI9HTHs= diff --git a/runner/proxy.go b/runner/proxy.go index 308c25b..3c2ab4c 100644 --- a/runner/proxy.go +++ b/runner/proxy.go @@ -12,6 +12,8 @@ import ( "strconv" "strings" "time" + + "github.com/andybalholm/brotli" ) var ( @@ -30,6 +32,15 @@ type Streamer interface { Stop() } +// contentEncoding represents the type of content encoding used in HTTP responses. +type contentEncoding int + +const ( + encodingNone contentEncoding = iota + encodingGzip + encodingBrotli +) + type Proxy struct { server *http.Server client *http.Client @@ -71,32 +82,37 @@ func (p *Proxy) BuildFailed(msg BuildFailedMsg) { } func (p *Proxy) injectLiveReload(resp *http.Response) (string, bool, error) { - reader := resp.Body - decodedGzip := false - if isGzipEncoded(resp.Header) { + var reader io.Reader = resp.Body + decoded := false + + switch detectContentEncoding(resp.Header) { + case encodingGzip: gzipReader, err := gzip.NewReader(resp.Body) if err != nil { return "", false, fmt.Errorf("proxy inject: failed to init gzip reader: %w", err) } defer gzipReader.Close() reader = gzipReader - decodedGzip = true + decoded = true + case encodingBrotli: + reader = brotli.NewReader(resp.Body) + decoded = true } buf := new(bytes.Buffer) if _, err := buf.ReadFrom(reader); err != nil { - return "", decodedGzip, fmt.Errorf("proxy inject: failed to read body from http response: %w", err) + return "", decoded, fmt.Errorf("proxy inject: failed to read body from http response: %w", err) } page := buf.String() // the script will be injected before the end of the body tag. In case the tag is missing, the injection will be skipped with no error. body := strings.LastIndex(page, "