0
Fork 0
mirror of https://github.com/caddyserver/caddy.git synced 2025-02-03 23:09:57 -05:00

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

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

* make linter happy, rename "Html" in identifiers to "HTML"
This commit is contained in:
Martin Bertschler 2017-03-12 23:41:49 +01:00 committed by Matt Holt
parent 5e48f0a412
commit 96bfb9f347
3 changed files with 78 additions and 62 deletions

View file

@ -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"
) )

View file

@ -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

View file

@ -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 (
) )
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 (
// '------ 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) {
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) {
}, },
// 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) {
}, },
// 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) {
}, },
// 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) {
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) {
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)
}
} }
} }