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>",
} }
...@@ -76,15 +77,16 @@ func TestServeHTTP(t *testing.T) { ...@@ -76,15 +77,16 @@ func TestServeHTTP(t *testing.T) {
movedPermanently := "Moved Permanently" movedPermanently := "Moved Permanently"
tests := []struct { tests := []struct {
url string url string
cleanedPath string cleanedPath string
acceptEncoding string acceptEncoding string
expectedLocation string expectedLocation string
expectedStatus int expectedStatus int
expectedBodyContent string expectedBodyContent string
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
{ {
...@@ -98,17 +100,19 @@ func TestServeHTTP(t *testing.T) { ...@@ -98,17 +100,19 @@ func TestServeHTTP(t *testing.T) {
}, },
// Test 2 - access existing file // Test 2 - access existing file
{ {
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
{ {
...@@ -148,10 +152,11 @@ func TestServeHTTP(t *testing.T) { ...@@ -148,10 +152,11 @@ func TestServeHTTP(t *testing.T) {
}, },
// Test 10 - access a index file directly // Test 10 - access a index file directly
{ {
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
{ {
...@@ -193,33 +198,36 @@ func TestServeHTTP(t *testing.T) { ...@@ -193,33 +198,36 @@ func TestServeHTTP(t *testing.T) {
}, },
// Test 18 - try to get pre-gzipped file. // Test 18 - try to get pre-gzipped file.
{ {
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