diff options
-rw-r--r-- | go.mod | 2 | ||||
-rw-r--r-- | go.sum | 4 | ||||
-rw-r--r-- | internal/serving/disk/helpers.go | 71 |
3 files changed, 41 insertions, 36 deletions
@@ -24,7 +24,7 @@ require ( github.com/stretchr/testify v1.7.0 github.com/tj/assert v0.0.3 // indirect github.com/tj/go-redirects v0.0.0-20180508180010-5c02ead0bbc5 - gitlab.com/feistel/go-contentencoding v0.0.0-20211129152627-d8d6a3107e17 + gitlab.com/feistel/go-contentencoding v1.0.0 gitlab.com/gitlab-org/go-mimedb v1.45.0 gitlab.com/gitlab-org/golang-archive-zip v0.1.1 gitlab.com/gitlab-org/labkit v1.12.0 @@ -441,8 +441,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -gitlab.com/feistel/go-contentencoding v0.0.0-20211129152627-d8d6a3107e17 h1:Lo8iYCdU0bkeUoFg9r3fIN08dj1gWGb+wTymcENkuR4= -gitlab.com/feistel/go-contentencoding v0.0.0-20211129152627-d8d6a3107e17/go.mod h1:xNYBUFP6IqNB5RX5NGm5IX+is7VvM3nBu2jBLADUOE4= +gitlab.com/feistel/go-contentencoding v1.0.0 h1:tBXZUv35f8AFsr7q7U38zZkhmPjSksfXC6VEh1MfbsI= +gitlab.com/feistel/go-contentencoding v1.0.0/go.mod h1:xNYBUFP6IqNB5RX5NGm5IX+is7VvM3nBu2jBLADUOE4= gitlab.com/gitlab-org/go-mimedb v1.45.0 h1:PO8dx6HEWzPYU6MQTYnCbpQEJzhJLW/Bh43+2VUHTgc= gitlab.com/gitlab-org/go-mimedb v1.45.0/go.mod h1:wa9y/zOSFKmTXLyBs4clz2FNVhZQmmEQM9TxslPAjZ0= gitlab.com/gitlab-org/golang-archive-zip v0.1.1 h1:35k9giivbxwF03+8A05Cm8YoxoakU8FBCj5gysjCTCE= diff --git a/internal/serving/disk/helpers.go b/internal/serving/disk/helpers.go index 5456724a..96360d49 100644 --- a/internal/serving/disk/helpers.go +++ b/internal/serving/disk/helpers.go @@ -5,27 +5,28 @@ import ( "io" "mime" "net/http" - "os" "path/filepath" "strconv" "strings" - "gitlab.com/gitlab-org/gitlab-pages/internal/httputil" + contentencoding "gitlab.com/feistel/go-contentencoding/encoding" + "gitlab.com/gitlab-org/gitlab-pages/internal/vfs" ) -var compressedEncodings = map[string]string{ - "br": ".br", - "gzip": ".gz", -} +var ( + // Server side content encoding priority. + supportedEncodings = contentencoding.Preference{ + contentencoding.Brotli: 1.0, + contentencoding.Gzip: 0.5, + contentencoding.Identity: 0.1, + } -// Server side content encoding priority. -// Map iteration order is not deterministic in go, so we need this array to specify the priority -// when the client doesn't provide one -var compressedEncodingsPriority = []string{ - "br", - "gzip", -} + compressedEncodings = map[string]string{ + contentencoding.Brotli: ".br", + contentencoding.Gzip: ".gz", + } +) func endsWithSlash(path string) bool { return strings.HasSuffix(path, "/") @@ -66,35 +67,39 @@ func (reader *Reader) handleContentEncoding(ctx context.Context, w http.Response return fullPath } - files := map[string]os.FileInfo{} + acceptHeader := r.Header.Get("Accept-Encoding") - // finding compressed files - for encoding, extension := range compressedEncodings { - path := fullPath + extension + // don't send compressed content if there's no accept-encoding header + if acceptHeader == "" { + return fullPath + } - // Ensure the file is not a symlink - if fi, err := root.Lstat(ctx, path); err == nil && fi.Mode().IsRegular() { - files[encoding] = fi - } + results, err := supportedEncodings.Negotiate(acceptHeader, contentencoding.AliasIdentity) + if err != nil { + return fullPath } - offers := make([]string, 0, len(files)+1) - for _, encoding := range compressedEncodingsPriority { - if _, ok := files[encoding]; ok { - offers = append(offers, encoding) - } + if len(results) == 0 { + return fullPath } - offers = append(offers, "identity") - acceptedEncoding := httputil.NegotiateContentEncoding(r, offers) + for _, encoding := range results { + if encoding == contentencoding.Identity { + break + } + + extension := compressedEncodings[encoding] + path := fullPath + extension - if fi, ok := files[acceptedEncoding]; ok { - w.Header().Set("Content-Encoding", acceptedEncoding) + // Ensure the file is not a symlink + if fi, err := root.Lstat(ctx, path); err == nil && fi.Mode().IsRegular() { + w.Header().Set("Content-Encoding", encoding) - // http.ServeContent doesn't set Content-Length if Content-Encoding is set - w.Header().Set("Content-Length", strconv.FormatInt(fi.Size(), 10)) + // http.ServeContent doesn't set Content-Length if Content-Encoding is set + w.Header().Set("Content-Length", strconv.FormatInt(fi.Size(), 10)) - return fullPath + compressedEncodings[acceptedEncoding] + return path + } } return fullPath |