summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorrouzier <[email protected]>2019-07-18 15:50:01 -0400
committerMatt Holt <[email protected]>2019-07-18 13:50:01 -0600
commit120811e7f728734c701dac4ec44a2934e2cca6fc (patch)
tree5ba7feb5cdb1dd55dd7fbb459b2128645f75e5f3
parent43458bda468e69b21c29a0bad93064136759c898 (diff)
downloadcaddy-120811e7f728734c701dac4ec44a2934e2cca6fc.tar.gz
caddy-120811e7f728734c701dac4ec44a2934e2cca6fc.zip
staticfiles: Support pre-compressed zstd, make etag content-encoding-aware (#2626)
* Add support for precompressed zstd files (rfc8478) * Avoid the hash lookup for the file extension. * Only calculate Etag once
-rw-r--r--caddyhttp/staticfiles/fileserver.go28
-rw-r--r--caddyhttp/staticfiles/fileserver_test.go19
2 files changed, 27 insertions, 20 deletions
diff --git a/caddyhttp/staticfiles/fileserver.go b/caddyhttp/staticfiles/fileserver.go
index 273498553..5690ceb93 100644
--- a/caddyhttp/staticfiles/fileserver.go
+++ b/caddyhttp/staticfiles/fileserver.go
@@ -184,15 +184,14 @@ func (fs FileServer) serveFile(w http.ResponseWriter, r *http.Request) (int, err
return http.StatusNotFound, nil
}
- etag := calculateEtag(d)
-
+ etagInfo := d
// look for compressed versions of the file on disk, if the client supports that encoding
for _, encoding := range staticEncodingPriority {
// see if the client accepts a compressed encoding we offer
acceptEncoding := strings.Split(r.Header.Get("Accept-Encoding"), ",")
accepted := false
for _, acc := range acceptEncoding {
- if strings.TrimSpace(acc) == encoding {
+ if strings.TrimSpace(acc) == encoding.name {
accepted = true
break
}
@@ -204,7 +203,7 @@ func (fs FileServer) serveFile(w http.ResponseWriter, r *http.Request) (int, err
}
// see if the compressed version of this file exists
- encodedFile, err := fs.Root.Open(reqPath + staticEncoding[encoding])
+ encodedFile, err := fs.Root.Open(reqPath + encoding.ext)
if err != nil {
continue
}
@@ -222,13 +221,15 @@ func (fs FileServer) serveFile(w http.ResponseWriter, r *http.Request) (int, err
// the encoded file is now what we're serving
f = encodedFile
- etag = calculateEtag(encodedFileInfo)
+ etagInfo = encodedFileInfo
w.Header().Add("Vary", "Accept-Encoding")
- w.Header().Set("Content-Encoding", encoding)
+ w.Header().Set("Content-Encoding", encoding.name)
w.Header().Set("Content-Length", strconv.FormatInt(encodedFileInfo.Size(), 10))
break
}
+ etag := calculateEtag(etagInfo)
+
// Set the ETag returned to the user-agent. Note that a conditional If-None-Match
// request is handled in http.ServeContent below, which checks against this ETag value.
w.Header().Set("ETag", etag)
@@ -279,16 +280,9 @@ var DefaultIndexPages = []string{
"default.txt",
}
-// staticEncoding is a map of content-encoding to a file extension.
-// If client accepts given encoding (via Accept-Encoding header) and compressed file with given extensions exists
-// it will be served to the client instead of original one.
-var staticEncoding = map[string]string{
- "gzip": ".gz",
- "br": ".br",
-}
-
// staticEncodingPriority is a list of preferred static encodings (most efficient compression to least one).
-var staticEncodingPriority = []string{
- "br",
- "gzip",
+var staticEncodingPriority = []struct{ name, ext string }{
+ {"zstd", ".zst"},
+ {"br", ".br"},
+ {"gzip", ".gz"},
}
diff --git a/caddyhttp/staticfiles/fileserver_test.go b/caddyhttp/staticfiles/fileserver_test.go
index 3eb10e3ad..a534d8c85 100644
--- a/caddyhttp/staticfiles/fileserver_test.go
+++ b/caddyhttp/staticfiles/fileserver_test.go
@@ -264,6 +264,17 @@ func TestServeHTTP(t *testing.T) {
expectedLocation: "https://foo/example.com/../",
expectedBodyContent: movedPermanently,
},
+ // Test 30 - try to get pre- file.
+ {
+ url: "https://foo/sub/gzipped.html",
+ acceptEncoding: "zstd",
+ expectedStatus: http.StatusOK,
+ expectedBodyContent: testFiles[webrootSubGzippedHTMLZst],
+ expectedEtag: `"2n9ci"`,
+ expectedVary: "Accept-Encoding",
+ expectedEncoding: "zstd",
+ expectedContentLength: strconv.Itoa(len(testFiles[webrootSubGzippedHTMLZst])),
+ },
}
for i, test := range tests {
@@ -546,6 +557,7 @@ var (
webrootSubGzippedHTML = filepath.Join(webrootName, "sub", "gzipped.html")
webrootSubGzippedHTMLGz = filepath.Join(webrootName, "sub", "gzipped.html.gz")
webrootSubGzippedHTMLBr = filepath.Join(webrootName, "sub", "gzipped.html.br")
+ webrootSubGzippedHTMLZst = filepath.Join(webrootName, "sub", "gzipped.html.zst")
webrootSubBrotliHTML = filepath.Join(webrootName, "sub", "brotli.html")
webrootSubBrotliHTMLGz = filepath.Join(webrootName, "sub", "brotli.html.gz")
webrootSubBrotliHTMLBr = filepath.Join(webrootName, "sub", "brotli.html.br")
@@ -573,9 +585,10 @@ var testFiles = map[string]string{
webrootSubGzippedHTML: "<h1>gzipped.html</h1>",
webrootSubGzippedHTMLGz: "1.gzipped.html.gz",
webrootSubGzippedHTMLBr: "2.gzipped.html.br",
- webrootSubBrotliHTML: "3.brotli.html",
- webrootSubBrotliHTMLGz: "4.brotli.html.gz",
- webrootSubBrotliHTMLBr: "5.brotli.html.br",
+ webrootSubGzippedHTMLZst: "3.gzipped.html.zst",
+ webrootSubBrotliHTML: "4.brotli.html",
+ webrootSubBrotliHTMLGz: "5.brotli.html.gz",
+ webrootSubBrotliHTMLBr: "6.brotli.html.br",
webrootSubBarDirWithIndexIndexHTML: "<h1>bar/dirwithindex/index.html</h1>",
}