Commit 96bfb9f3 authored by Martin Bertschler's avatar Martin Bertschler Committed by Matt Holt

staticfiles: add Content-Length header (closes #1479) (#1492)

* staticfiles: add Content-Length header (closes #1479)

* make linter happy, rename "Html" in identifiers to "HTML"
parent 5e48f0a4
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ import (
"strings" "strings"
"errors" "errors"
"github.com/mholt/caddy" "github.com/mholt/caddy"
"github.com/mholt/caddy/caddyhttp/httpserver" "github.com/mholt/caddy/caddyhttp/httpserver"
) )
......
...@@ -201,6 +201,7 @@ func (fs FileServer) serveFile(w http.ResponseWriter, r *http.Request, name stri ...@@ -201,6 +201,7 @@ func (fs FileServer) serveFile(w http.ResponseWriter, r *http.Request, name stri
w.Header().Add("Vary", "Accept-Encoding") w.Header().Add("Vary", "Accept-Encoding")
w.Header().Set("Content-Encoding", encoding) w.Header().Set("Content-Encoding", encoding)
w.Header().Set("Content-Length", strconv.FormatInt(encodedFileInfo.Size(), 10))
defer f.Close() defer f.Close()
break break
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"net/url" "net/url"
"os" "os"
"path/filepath" "path/filepath"
"strconv"
"strings" "strings"
"testing" "testing"
"time" "time"
...@@ -23,16 +24,16 @@ var ( ...@@ -23,16 +24,16 @@ var (
) )
var ( var (
webrootFile1Html = filepath.Join("webroot", "file1.html") webrootFile1HTML = filepath.Join("webroot", "file1.html")
webrootDirFile2Html = filepath.Join("webroot", "dir", "file2.html") webrootDirFile2HTML = filepath.Join("webroot", "dir", "file2.html")
webrootDirHiddenHtml = filepath.Join("webroot", "dir", "hidden.html") webrootDirHiddenHTML = filepath.Join("webroot", "dir", "hidden.html")
webrootDirwithindexIndeHtml = filepath.Join("webroot", "dirwithindex", "index.html") webrootDirwithindexIndeHTML = filepath.Join("webroot", "dirwithindex", "index.html")
webrootSubGzippedHtml = filepath.Join("webroot", "sub", "gzipped.html") webrootSubGzippedHTML = filepath.Join("webroot", "sub", "gzipped.html")
webrootSubGzippedHtmlGz = filepath.Join("webroot", "sub", "gzipped.html.gz") webrootSubGzippedHTMLGz = filepath.Join("webroot", "sub", "gzipped.html.gz")
webrootSubGzippedHtmlBr = filepath.Join("webroot", "sub", "gzipped.html.br") webrootSubGzippedHTMLBr = filepath.Join("webroot", "sub", "gzipped.html.br")
webrootSubBrotliHtml = filepath.Join("webroot", "sub", "brotli.html") webrootSubBrotliHTML = filepath.Join("webroot", "sub", "brotli.html")
webrootSubBrotliHtmlGz = filepath.Join("webroot", "sub", "brotli.html.gz") webrootSubBrotliHTMLGz = filepath.Join("webroot", "sub", "brotli.html.gz")
webrootSubBrotliHtmlBr = filepath.Join("webroot", "sub", "brotli.html.br") webrootSubBrotliHTMLBr = filepath.Join("webroot", "sub", "brotli.html.br")
webrootSubBarDirWithIndexIndexHTML = filepath.Join("webroot", "bar", "dirwithindex", "index.html") webrootSubBarDirWithIndexIndexHTML = filepath.Join("webroot", "bar", "dirwithindex", "index.html")
) )
...@@ -49,16 +50,16 @@ var ( ...@@ -49,16 +50,16 @@ var (
// '------ hidden.html // '------ hidden.html
var testFiles = map[string]string{ var testFiles = map[string]string{
"unreachable.html": "<h1>must not leak</h1>", "unreachable.html": "<h1>must not leak</h1>",
webrootFile1Html: "<h1>file1.html</h1>", webrootFile1HTML: "<h1>file1.html</h1>",
webrootDirFile2Html: "<h1>dir/file2.html</h1>", webrootDirFile2HTML: "<h1>dir/file2.html</h1>",
webrootDirwithindexIndeHtml: "<h1>dirwithindex/index.html</h1>", webrootDirwithindexIndeHTML: "<h1>dirwithindex/index.html</h1>",
webrootDirHiddenHtml: "<h1>dir/hidden.html</h1>", webrootDirHiddenHTML: "<h1>dir/hidden.html</h1>",
webrootSubGzippedHtml: "<h1>gzipped.html</h1>", webrootSubGzippedHTML: "<h1>gzipped.html</h1>",
webrootSubGzippedHtmlGz: "1.gzipped.html.gz", webrootSubGzippedHTMLGz: "1.gzipped.html.gz",
webrootSubGzippedHtmlBr: "2.gzipped.html.br", webrootSubGzippedHTMLBr: "2.gzipped.html.br",
webrootSubBrotliHtml: "3.brotli.html", webrootSubBrotliHTML: "3.brotli.html",
webrootSubBrotliHtmlGz: "4.brotli.html.gz", webrootSubBrotliHTMLGz: "4.brotli.html.gz",
webrootSubBrotliHtmlBr: "5.brotli.html.br", webrootSubBrotliHTMLBr: "5.brotli.html.br",
webrootSubBarDirWithIndexIndexHTML: "<h1>bar/dirwithindex/index.html</h1>", webrootSubBarDirWithIndexIndexHTML: "<h1>bar/dirwithindex/index.html</h1>",
} }
...@@ -85,6 +86,7 @@ func TestServeHTTP(t *testing.T) { ...@@ -85,6 +86,7 @@ func TestServeHTTP(t *testing.T) {
expectedEtag string expectedEtag string
expectedVary string expectedVary string
expectedEncoding string expectedEncoding string
expectedContentLength string
}{ }{
// Test 0 - access without any path // Test 0 - access without any path
{ {
...@@ -100,15 +102,17 @@ func TestServeHTTP(t *testing.T) { ...@@ -100,15 +102,17 @@ func TestServeHTTP(t *testing.T) {
{ {
url: "https://foo/file1.html", url: "https://foo/file1.html",
expectedStatus: http.StatusOK, expectedStatus: http.StatusOK,
expectedBodyContent: testFiles[webrootFile1Html], expectedBodyContent: testFiles[webrootFile1HTML],
expectedEtag: `"2n9cj"`, expectedEtag: `"2n9cj"`,
expectedContentLength: strconv.Itoa(len(testFiles[webrootFile1HTML])),
}, },
// Test 3 - access folder with index file with trailing slash // Test 3 - access folder with index file with trailing slash
{ {
url: "https://foo/dirwithindex/", url: "https://foo/dirwithindex/",
expectedStatus: http.StatusOK, expectedStatus: http.StatusOK,
expectedBodyContent: testFiles[webrootDirwithindexIndeHtml], expectedBodyContent: testFiles[webrootDirwithindexIndeHTML],
expectedEtag: `"2n9cw"`, expectedEtag: `"2n9cw"`,
expectedContentLength: strconv.Itoa(len(testFiles[webrootDirwithindexIndeHTML])),
}, },
// Test 4 - access folder with index file without trailing slash // Test 4 - access folder with index file without trailing slash
{ {
...@@ -150,8 +154,9 @@ func TestServeHTTP(t *testing.T) { ...@@ -150,8 +154,9 @@ func TestServeHTTP(t *testing.T) {
{ {
url: "https://foo/dirwithindex/index.html", url: "https://foo/dirwithindex/index.html",
expectedStatus: http.StatusOK, expectedStatus: http.StatusOK,
expectedBodyContent: testFiles[webrootDirwithindexIndeHtml], expectedBodyContent: testFiles[webrootDirwithindexIndeHTML],
expectedEtag: `"2n9cw"`, expectedEtag: `"2n9cw"`,
expectedContentLength: strconv.Itoa(len(testFiles[webrootDirwithindexIndeHTML])),
}, },
// Test 11 - send a request with query params // Test 11 - send a request with query params
{ {
...@@ -196,30 +201,33 @@ func TestServeHTTP(t *testing.T) { ...@@ -196,30 +201,33 @@ func TestServeHTTP(t *testing.T) {
url: "https://foo/sub/gzipped.html", url: "https://foo/sub/gzipped.html",
acceptEncoding: "gzip", acceptEncoding: "gzip",
expectedStatus: http.StatusOK, expectedStatus: http.StatusOK,
expectedBodyContent: testFiles[webrootSubGzippedHtmlGz], expectedBodyContent: testFiles[webrootSubGzippedHTMLGz],
expectedEtag: `"2n9ch"`, expectedEtag: `"2n9ch"`,
expectedVary: "Accept-Encoding", expectedVary: "Accept-Encoding",
expectedEncoding: "gzip", expectedEncoding: "gzip",
expectedContentLength: strconv.Itoa(len(testFiles[webrootSubGzippedHTMLGz])),
}, },
// Test 19 - try to get pre-brotli encoded file. // Test 19 - try to get pre-brotli encoded file.
{ {
url: "https://foo/sub/brotli.html", url: "https://foo/sub/brotli.html",
acceptEncoding: "br,gzip", acceptEncoding: "br,gzip",
expectedStatus: http.StatusOK, expectedStatus: http.StatusOK,
expectedBodyContent: testFiles[webrootSubBrotliHtmlBr], expectedBodyContent: testFiles[webrootSubBrotliHTMLBr],
expectedEtag: `"2n9cg"`, expectedEtag: `"2n9cg"`,
expectedVary: "Accept-Encoding", expectedVary: "Accept-Encoding",
expectedEncoding: "br", expectedEncoding: "br",
expectedContentLength: strconv.Itoa(len(testFiles[webrootSubBrotliHTMLBr])),
}, },
// Test 20 - not allowed to get pre-brotli encoded file. // Test 20 - not allowed to get pre-brotli encoded file.
{ {
url: "https://foo/sub/brotli.html", url: "https://foo/sub/brotli.html",
acceptEncoding: "nicebrew", // contains "br" substring but not "br" acceptEncoding: "nicebrew", // contains "br" substring but not "br"
expectedStatus: http.StatusOK, expectedStatus: http.StatusOK,
expectedBodyContent: testFiles[webrootSubBrotliHtml], expectedBodyContent: testFiles[webrootSubBrotliHTML],
expectedEtag: `"2n9cd"`, expectedEtag: `"2n9cd"`,
expectedVary: "", expectedVary: "",
expectedEncoding: "", expectedEncoding: "",
expectedContentLength: strconv.Itoa(len(testFiles[webrootSubBrotliHTML])),
}, },
// Test 20 - treat existing file as a directory. // Test 20 - treat existing file as a directory.
{ {
...@@ -280,6 +288,7 @@ func TestServeHTTP(t *testing.T) { ...@@ -280,6 +288,7 @@ func TestServeHTTP(t *testing.T) {
body := responseRecorder.Body.String() body := responseRecorder.Body.String()
vary := responseRecorder.Header().Get("Vary") vary := responseRecorder.Header().Get("Vary")
encoding := responseRecorder.Header().Get("Content-Encoding") encoding := responseRecorder.Header().Get("Content-Encoding")
length := responseRecorder.Header().Get("Content-Length")
// check if error matches expectations // check if error matches expectations
if err != nil { if err != nil {
...@@ -317,6 +326,11 @@ func TestServeHTTP(t *testing.T) { ...@@ -317,6 +326,11 @@ func TestServeHTTP(t *testing.T) {
t.Errorf("Test %d: Expected Location header %q, found %q", i, test.expectedLocation, l) 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)
}
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment