diff --git a/caddyhttp/gzip/gzip.go b/caddyhttp/gzip/gzip.go
index d2a790a6a..2389fd99e 100644
--- a/caddyhttp/gzip/gzip.go
+++ b/caddyhttp/gzip/gzip.go
@@ -12,6 +12,7 @@ import (
"strings"
"errors"
+
"github.com/mholt/caddy"
"github.com/mholt/caddy/caddyhttp/httpserver"
)
diff --git a/caddyhttp/staticfiles/fileserver.go b/caddyhttp/staticfiles/fileserver.go
index c96cc37a4..6db0d8ea3 100644
--- a/caddyhttp/staticfiles/fileserver.go
+++ b/caddyhttp/staticfiles/fileserver.go
@@ -201,6 +201,7 @@ func (fs FileServer) serveFile(w http.ResponseWriter, r *http.Request, name stri
w.Header().Add("Vary", "Accept-Encoding")
w.Header().Set("Content-Encoding", encoding)
+ w.Header().Set("Content-Length", strconv.FormatInt(encodedFileInfo.Size(), 10))
defer f.Close()
break
diff --git a/caddyhttp/staticfiles/fileserver_test.go b/caddyhttp/staticfiles/fileserver_test.go
index 058ad7cf6..103d9265b 100644
--- a/caddyhttp/staticfiles/fileserver_test.go
+++ b/caddyhttp/staticfiles/fileserver_test.go
@@ -8,6 +8,7 @@ import (
"net/url"
"os"
"path/filepath"
+ "strconv"
"strings"
"testing"
"time"
@@ -23,16 +24,16 @@ var (
)
var (
- webrootFile1Html = filepath.Join("webroot", "file1.html")
- webrootDirFile2Html = filepath.Join("webroot", "dir", "file2.html")
- webrootDirHiddenHtml = filepath.Join("webroot", "dir", "hidden.html")
- webrootDirwithindexIndeHtml = filepath.Join("webroot", "dirwithindex", "index.html")
- webrootSubGzippedHtml = filepath.Join("webroot", "sub", "gzipped.html")
- webrootSubGzippedHtmlGz = filepath.Join("webroot", "sub", "gzipped.html.gz")
- webrootSubGzippedHtmlBr = filepath.Join("webroot", "sub", "gzipped.html.br")
- webrootSubBrotliHtml = filepath.Join("webroot", "sub", "brotli.html")
- webrootSubBrotliHtmlGz = filepath.Join("webroot", "sub", "brotli.html.gz")
- webrootSubBrotliHtmlBr = filepath.Join("webroot", "sub", "brotli.html.br")
+ webrootFile1HTML = filepath.Join("webroot", "file1.html")
+ webrootDirFile2HTML = filepath.Join("webroot", "dir", "file2.html")
+ webrootDirHiddenHTML = filepath.Join("webroot", "dir", "hidden.html")
+ webrootDirwithindexIndeHTML = filepath.Join("webroot", "dirwithindex", "index.html")
+ webrootSubGzippedHTML = filepath.Join("webroot", "sub", "gzipped.html")
+ webrootSubGzippedHTMLGz = filepath.Join("webroot", "sub", "gzipped.html.gz")
+ webrootSubGzippedHTMLBr = filepath.Join("webroot", "sub", "gzipped.html.br")
+ webrootSubBrotliHTML = filepath.Join("webroot", "sub", "brotli.html")
+ webrootSubBrotliHTMLGz = filepath.Join("webroot", "sub", "brotli.html.gz")
+ webrootSubBrotliHTMLBr = filepath.Join("webroot", "sub", "brotli.html.br")
webrootSubBarDirWithIndexIndexHTML = filepath.Join("webroot", "bar", "dirwithindex", "index.html")
)
@@ -49,16 +50,16 @@ var (
// '------ hidden.html
var testFiles = map[string]string{
"unreachable.html": "
must not leak
",
- webrootFile1Html: "file1.html
",
- webrootDirFile2Html: "dir/file2.html
",
- webrootDirwithindexIndeHtml: "dirwithindex/index.html
",
- webrootDirHiddenHtml: "dir/hidden.html
",
- webrootSubGzippedHtml: "gzipped.html
",
- webrootSubGzippedHtmlGz: "1.gzipped.html.gz",
- webrootSubGzippedHtmlBr: "2.gzipped.html.br",
- webrootSubBrotliHtml: "3.brotli.html",
- webrootSubBrotliHtmlGz: "4.brotli.html.gz",
- webrootSubBrotliHtmlBr: "5.brotli.html.br",
+ webrootFile1HTML: "file1.html
",
+ webrootDirFile2HTML: "dir/file2.html
",
+ webrootDirwithindexIndeHTML: "dirwithindex/index.html
",
+ webrootDirHiddenHTML: "dir/hidden.html
",
+ webrootSubGzippedHTML: "gzipped.html
",
+ webrootSubGzippedHTMLGz: "1.gzipped.html.gz",
+ webrootSubGzippedHTMLBr: "2.gzipped.html.br",
+ webrootSubBrotliHTML: "3.brotli.html",
+ webrootSubBrotliHTMLGz: "4.brotli.html.gz",
+ webrootSubBrotliHTMLBr: "5.brotli.html.br",
webrootSubBarDirWithIndexIndexHTML: "bar/dirwithindex/index.html
",
}
@@ -76,15 +77,16 @@ func TestServeHTTP(t *testing.T) {
movedPermanently := "Moved Permanently"
tests := []struct {
- url string
- cleanedPath string
- acceptEncoding string
- expectedLocation string
- expectedStatus int
- expectedBodyContent string
- expectedEtag string
- expectedVary string
- expectedEncoding string
+ url string
+ cleanedPath string
+ acceptEncoding string
+ expectedLocation string
+ expectedStatus int
+ expectedBodyContent string
+ expectedEtag string
+ expectedVary string
+ expectedEncoding string
+ expectedContentLength string
}{
// Test 0 - access without any path
{
@@ -98,17 +100,19 @@ func TestServeHTTP(t *testing.T) {
},
// Test 2 - access existing file
{
- url: "https://foo/file1.html",
- expectedStatus: http.StatusOK,
- expectedBodyContent: testFiles[webrootFile1Html],
- expectedEtag: `"2n9cj"`,
+ url: "https://foo/file1.html",
+ expectedStatus: http.StatusOK,
+ expectedBodyContent: testFiles[webrootFile1HTML],
+ expectedEtag: `"2n9cj"`,
+ expectedContentLength: strconv.Itoa(len(testFiles[webrootFile1HTML])),
},
// Test 3 - access folder with index file with trailing slash
{
- url: "https://foo/dirwithindex/",
- expectedStatus: http.StatusOK,
- expectedBodyContent: testFiles[webrootDirwithindexIndeHtml],
- expectedEtag: `"2n9cw"`,
+ url: "https://foo/dirwithindex/",
+ expectedStatus: http.StatusOK,
+ expectedBodyContent: testFiles[webrootDirwithindexIndeHTML],
+ expectedEtag: `"2n9cw"`,
+ expectedContentLength: strconv.Itoa(len(testFiles[webrootDirwithindexIndeHTML])),
},
// Test 4 - access folder with index file without trailing slash
{
@@ -148,10 +152,11 @@ func TestServeHTTP(t *testing.T) {
},
// Test 10 - access a index file directly
{
- url: "https://foo/dirwithindex/index.html",
- expectedStatus: http.StatusOK,
- expectedBodyContent: testFiles[webrootDirwithindexIndeHtml],
- expectedEtag: `"2n9cw"`,
+ url: "https://foo/dirwithindex/index.html",
+ expectedStatus: http.StatusOK,
+ expectedBodyContent: testFiles[webrootDirwithindexIndeHTML],
+ expectedEtag: `"2n9cw"`,
+ expectedContentLength: strconv.Itoa(len(testFiles[webrootDirwithindexIndeHTML])),
},
// Test 11 - send a request with query params
{
@@ -193,33 +198,36 @@ func TestServeHTTP(t *testing.T) {
},
// Test 18 - try to get pre-gzipped file.
{
- url: "https://foo/sub/gzipped.html",
- acceptEncoding: "gzip",
- expectedStatus: http.StatusOK,
- expectedBodyContent: testFiles[webrootSubGzippedHtmlGz],
- expectedEtag: `"2n9ch"`,
- expectedVary: "Accept-Encoding",
- expectedEncoding: "gzip",
+ url: "https://foo/sub/gzipped.html",
+ acceptEncoding: "gzip",
+ expectedStatus: http.StatusOK,
+ expectedBodyContent: testFiles[webrootSubGzippedHTMLGz],
+ expectedEtag: `"2n9ch"`,
+ expectedVary: "Accept-Encoding",
+ expectedEncoding: "gzip",
+ expectedContentLength: strconv.Itoa(len(testFiles[webrootSubGzippedHTMLGz])),
},
// Test 19 - try to get pre-brotli encoded file.
{
- url: "https://foo/sub/brotli.html",
- acceptEncoding: "br,gzip",
- expectedStatus: http.StatusOK,
- expectedBodyContent: testFiles[webrootSubBrotliHtmlBr],
- expectedEtag: `"2n9cg"`,
- expectedVary: "Accept-Encoding",
- expectedEncoding: "br",
+ url: "https://foo/sub/brotli.html",
+ acceptEncoding: "br,gzip",
+ expectedStatus: http.StatusOK,
+ expectedBodyContent: testFiles[webrootSubBrotliHTMLBr],
+ expectedEtag: `"2n9cg"`,
+ expectedVary: "Accept-Encoding",
+ expectedEncoding: "br",
+ expectedContentLength: strconv.Itoa(len(testFiles[webrootSubBrotliHTMLBr])),
},
// Test 20 - not allowed to get pre-brotli encoded file.
{
- url: "https://foo/sub/brotli.html",
- acceptEncoding: "nicebrew", // contains "br" substring but not "br"
- expectedStatus: http.StatusOK,
- expectedBodyContent: testFiles[webrootSubBrotliHtml],
- expectedEtag: `"2n9cd"`,
- expectedVary: "",
- expectedEncoding: "",
+ url: "https://foo/sub/brotli.html",
+ acceptEncoding: "nicebrew", // contains "br" substring but not "br"
+ expectedStatus: http.StatusOK,
+ expectedBodyContent: testFiles[webrootSubBrotliHTML],
+ expectedEtag: `"2n9cd"`,
+ expectedVary: "",
+ expectedEncoding: "",
+ expectedContentLength: strconv.Itoa(len(testFiles[webrootSubBrotliHTML])),
},
// Test 20 - treat existing file as a directory.
{
@@ -280,6 +288,7 @@ func TestServeHTTP(t *testing.T) {
body := responseRecorder.Body.String()
vary := responseRecorder.Header().Get("Vary")
encoding := responseRecorder.Header().Get("Content-Encoding")
+ length := responseRecorder.Header().Get("Content-Length")
// check if error matches expectations
if err != nil {
@@ -317,6 +326,11 @@ func TestServeHTTP(t *testing.T) {
t.Errorf("Test %d: Expected Location header %q, found %q", i, test.expectedLocation, l)
}
}
+
+ // check content length
+ if test.expectedContentLength != length {
+ t.Errorf("Test %d: Expected Content-Length header %s, found %s", i, test.expectedContentLength, length)
+ }
}
}