File matcher enforces trailing-slash convention to match dirs/files

This commit is contained in:
Matthew Holt 2019-09-06 13:32:02 -06:00
parent 4bd9496525
commit 97ace2a39e
No known key found for this signature in database
GPG Key ID: 2A349DD577D586A5

View File

@ -19,6 +19,7 @@ import (
"net/http"
"os"
"path"
"strings"
"time"
"github.com/caddyserver/caddy/v2"
@ -149,7 +150,7 @@ func (m MatchFile) selectFile(r *http.Request) (rel, abs string, matched bool) {
for _, f := range m.TryFiles {
suffix := path.Clean(repl.ReplaceAll(f, ""))
fullpath := sanitizedPathJoin(root, suffix)
if fileExists(fullpath) {
if strictFileExists(fullpath) {
return suffix, fullpath, true
}
}
@ -207,22 +208,33 @@ func (m MatchFile) selectFile(r *http.Request) (rel, abs string, matched bool) {
return
}
// fileExists returns true if file exists,
// false if it doesn't, or false if there
// was any other error.
func fileExists(file string) bool {
_, err := os.Stat(file)
if err == nil {
return true
} else if os.IsNotExist(err) {
return false
} else {
// we don't know if it exists,
// so assume it doesn't, since
// there must have been some
// other error anyway
// 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 (