diff options
Diffstat (limited to 'modules/caddyhttp/fileserver')
-rw-r--r-- | modules/caddyhttp/fileserver/caddyfile.go | 6 | ||||
-rw-r--r-- | modules/caddyhttp/fileserver/matcher.go | 50 |
2 files changed, 40 insertions, 16 deletions
diff --git a/modules/caddyhttp/fileserver/caddyfile.go b/modules/caddyhttp/fileserver/caddyfile.go index 6480598..b7cb311 100644 --- a/modules/caddyhttp/fileserver/caddyfile.go +++ b/modules/caddyhttp/fileserver/caddyfile.go @@ -71,11 +71,6 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) } } - // if no root was configured explicitly, use site root - if fsrv.Root == "" { - fsrv.Root = "{http.var.root}" - } - // hide the Caddyfile (and any imported Caddyfiles) if configFiles := h.Caddyfiles(); len(configFiles) > 0 { for _, file := range configFiles { @@ -104,7 +99,6 @@ func parseTryFiles(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error) matcherSet := map[string]json.RawMessage{ "file": h.JSON(MatchFile{ - Root: "{http.var.root}", TryFiles: try, }, nil), } diff --git a/modules/caddyhttp/fileserver/matcher.go b/modules/caddyhttp/fileserver/matcher.go index b091250..fde086e 100644 --- a/modules/caddyhttp/fileserver/matcher.go +++ b/modules/caddyhttp/fileserver/matcher.go @@ -18,6 +18,8 @@ import ( "fmt" "net/http" "os" + "path" + "strings" "time" "github.com/caddyserver/caddy/v2" @@ -87,8 +89,13 @@ func (m *MatchFile) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { } } } + return nil +} + +// Provision sets up m's defaults. +func (m *MatchFile) Provision(_ caddy.Context) error { if m.Root == "" { - m.Root = "{http.var.root}" + m.Root = "{http.vars.root}" } return nil } @@ -141,9 +148,9 @@ func (m MatchFile) selectFile(r *http.Request) (rel, abs string, matched bool) { switch m.TryPolicy { case "", tryPolicyFirstExist: for _, f := range m.TryFiles { - suffix := repl.ReplaceAll(f, "") + suffix := path.Clean(repl.ReplaceAll(f, "")) fullpath := sanitizedPathJoin(root, suffix) - if fileExists(fullpath) { + if strictFileExists(fullpath) { return suffix, fullpath, true } } @@ -153,7 +160,7 @@ func (m MatchFile) selectFile(r *http.Request) (rel, abs string, matched bool) { var largestFilename string var largestSuffix string for _, f := range m.TryFiles { - suffix := repl.ReplaceAll(f, "") + suffix := path.Clean(repl.ReplaceAll(f, "")) fullpath := sanitizedPathJoin(root, suffix) info, err := os.Stat(fullpath) if err == nil && info.Size() > largestSize { @@ -169,7 +176,7 @@ func (m MatchFile) selectFile(r *http.Request) (rel, abs string, matched bool) { var smallestFilename string var smallestSuffix string for _, f := range m.TryFiles { - suffix := repl.ReplaceAll(f, "") + suffix := path.Clean(repl.ReplaceAll(f, "")) fullpath := sanitizedPathJoin(root, suffix) info, err := os.Stat(fullpath) if err == nil && (smallestSize == 0 || info.Size() < smallestSize) { @@ -185,7 +192,7 @@ func (m MatchFile) selectFile(r *http.Request) (rel, abs string, matched bool) { var recentFilename string var recentSuffix string for _, f := range m.TryFiles { - suffix := repl.ReplaceAll(f, "") + suffix := path.Clean(repl.ReplaceAll(f, "")) fullpath := sanitizedPathJoin(root, suffix) info, err := os.Stat(fullpath) if err == nil && @@ -201,10 +208,33 @@ func (m MatchFile) selectFile(r *http.Request) (rel, abs string, matched bool) { return } -// fileExists returns true if file exists. -func fileExists(file string) bool { - _, err := os.Stat(file) - return !os.IsNotExist(err) +// strictFileExists returns true if file exists +// and matches the convention of the given file +// path. If the path ends in a forward slash, +// the file must also be a directory; if it does +// NOT end in a forward slash, the file must NOT +// be a directory. +func strictFileExists(file string) bool { + stat, err := os.Stat(file) + if err != nil { + // in reality, this can be any error + // such as permission or even obscure + // ones like "is not a directory" (when + // trying to stat a file within a file); + // in those cases we can't be sure if + // the file exists, so we just treat any + // error as if it does not exist; see + // https://stackoverflow.com/a/12518877/1048862 + return false + } + if strings.HasSuffix(file, "/") { + // by convention, file paths ending + // in a slash must be a directory + return stat.IsDir() + } + // by convention, file paths NOT ending + // in a slash must NOT be a directory + return !stat.IsDir() } const ( |