summaryrefslogtreecommitdiff
path: root/modules/caddyhttp/fileserver
diff options
context:
space:
mode:
authorFrancis Lavoie <lavofr@gmail.com>2020-12-04 19:12:13 -0500
committerGitHub <noreply@github.com>2020-12-04 17:12:13 -0700
commit6e9ac248dd5c2f7a4cd4e37ff277a86c18085be6 (patch)
treea6c9da30da87e8cba6986f43c6483dadf4919e6f /modules/caddyhttp/fileserver
parent5643dc3fb9e84b1dc862aa96bc5474d06f36d9c4 (diff)
fastcgi: Set PATH_INFO to file matcher remainder as fallback (#3739)
* fastcgi: Set PATH_INFO to file matcher remainder as fallback * fastcgi: Avoid changing scriptName when not necessary * Stylistic tweaks Co-authored-by: Matthew Holt <mholt@users.noreply.github.com>
Diffstat (limited to 'modules/caddyhttp/fileserver')
-rw-r--r--modules/caddyhttp/fileserver/matcher.go51
-rw-r--r--modules/caddyhttp/fileserver/matcher_test.go8
2 files changed, 37 insertions, 22 deletions
diff --git a/modules/caddyhttp/fileserver/matcher.go b/modules/caddyhttp/fileserver/matcher.go
index c103b03..44ef9ed 100644
--- a/modules/caddyhttp/fileserver/matcher.go
+++ b/modules/caddyhttp/fileserver/matcher.go
@@ -44,6 +44,8 @@ func init() {
// of the matched file.
// - `{http.matchers.file.type}` Set to "directory" if
// the matched file is a directory, "file" otherwise.
+// - `{http.matchers.file.remainder}` Set to the remainder
+// of the path if the path was split by `split_path`.
type MatchFile struct {
// The root directory, used for creating absolute
// file paths, and required when working with
@@ -155,11 +157,12 @@ func (m MatchFile) Validate() error {
}
// Match returns true if r matches m. Returns true
-// if a file was matched. If so, three placeholders
+// if a file was matched. If so, four placeholders
// will be available:
// - http.matchers.file.relative
// - http.matchers.file.absolute
// - http.matchers.file.type
+// - http.matchers.file.remainder
func (m MatchFile) Match(r *http.Request) bool {
return m.selectFile(r)
}
@@ -179,19 +182,20 @@ func (m MatchFile) selectFile(r *http.Request) (matched bool) {
}
// common preparation of the file into parts
- prepareFilePath := func(file string) (string, string) {
- suffix := m.firstSplit(path.Clean(repl.ReplaceAll(file, "")))
+ prepareFilePath := func(file string) (suffix, fullpath, remainder string) {
+ suffix, remainder = m.firstSplit(path.Clean(repl.ReplaceAll(file, "")))
if strings.HasSuffix(file, "/") {
suffix += "/"
}
- fullpath := sanitizedPathJoin(root, suffix)
- return suffix, fullpath
+ fullpath = sanitizedPathJoin(root, suffix)
+ return
}
// sets up the placeholders for the matched file
- setPlaceholders := func(info os.FileInfo, rel string, abs string) {
+ setPlaceholders := func(info os.FileInfo, rel string, abs string, remainder string) {
repl.Set("http.matchers.file.relative", rel)
repl.Set("http.matchers.file.absolute", abs)
+ repl.Set("http.matchers.file.remainder", remainder)
fileType := "file"
if info.IsDir() {
@@ -203,9 +207,9 @@ func (m MatchFile) selectFile(r *http.Request) (matched bool) {
switch m.TryPolicy {
case "", tryPolicyFirstExist:
for _, f := range m.TryFiles {
- suffix, fullpath := prepareFilePath(f)
+ suffix, fullpath, remainder := prepareFilePath(f)
if info, exists := strictFileExists(fullpath); exists {
- setPlaceholders(info, suffix, fullpath)
+ setPlaceholders(info, suffix, fullpath, remainder)
return true
}
}
@@ -214,52 +218,58 @@ func (m MatchFile) selectFile(r *http.Request) (matched bool) {
var largestSize int64
var largestFilename string
var largestSuffix string
+ var remainder string
var info os.FileInfo
for _, f := range m.TryFiles {
- suffix, fullpath := prepareFilePath(f)
+ suffix, fullpath, splitRemainder := prepareFilePath(f)
info, err := os.Stat(fullpath)
if err == nil && info.Size() > largestSize {
largestSize = info.Size()
largestFilename = fullpath
largestSuffix = suffix
+ remainder = splitRemainder
}
}
- setPlaceholders(info, largestSuffix, largestFilename)
+ setPlaceholders(info, largestSuffix, largestFilename, remainder)
return true
case tryPolicySmallestSize:
var smallestSize int64
var smallestFilename string
var smallestSuffix string
+ var remainder string
var info os.FileInfo
for _, f := range m.TryFiles {
- suffix, fullpath := prepareFilePath(f)
+ suffix, fullpath, splitRemainder := prepareFilePath(f)
info, err := os.Stat(fullpath)
if err == nil && (smallestSize == 0 || info.Size() < smallestSize) {
smallestSize = info.Size()
smallestFilename = fullpath
smallestSuffix = suffix
+ remainder = splitRemainder
}
}
- setPlaceholders(info, smallestSuffix, smallestFilename)
+ setPlaceholders(info, smallestSuffix, smallestFilename, remainder)
return true
case tryPolicyMostRecentlyMod:
var recentDate time.Time
var recentFilename string
var recentSuffix string
+ var remainder string
var info os.FileInfo
for _, f := range m.TryFiles {
- suffix, fullpath := prepareFilePath(f)
+ suffix, fullpath, splitRemainder := prepareFilePath(f)
info, err := os.Stat(fullpath)
if err == nil &&
(recentDate.IsZero() || info.ModTime().After(recentDate)) {
recentDate = info.ModTime()
recentFilename = fullpath
recentSuffix = suffix
+ remainder = splitRemainder
}
}
- setPlaceholders(info, recentSuffix, recentFilename)
+ setPlaceholders(info, recentSuffix, recentFilename, remainder)
return true
}
@@ -297,10 +307,11 @@ func strictFileExists(file string) (os.FileInfo, bool) {
// firstSplit returns the first result where the path
// can be split in two by a value in m.SplitPath. The
-// result is the first piece of the path that ends with
-// in the split value. Returns the path as-is if the
-// path cannot be split.
-func (m MatchFile) firstSplit(path string) string {
+// return values are the first piece of the path that
+// ends with the split substring and the remainder.
+// If the path cannot be split, the path is returned
+// as-is (with no remainder).
+func (m MatchFile) firstSplit(path string) (splitPart, remainder string) {
for _, split := range m.SplitPath {
if idx := indexFold(path, split); idx > -1 {
pos := idx + len(split)
@@ -308,10 +319,10 @@ func (m MatchFile) firstSplit(path string) string {
if pos != len(path) && !strings.HasPrefix(path[pos:], "/") {
continue
}
- return path[:pos]
+ return path[:pos], path[pos:]
}
}
- return path
+ return path, ""
}
// There is no strings.IndexFold() function like there is strings.EqualFold(),
diff --git a/modules/caddyhttp/fileserver/matcher_test.go b/modules/caddyhttp/fileserver/matcher_test.go
index ddd4f78..e319907 100644
--- a/modules/caddyhttp/fileserver/matcher_test.go
+++ b/modules/caddyhttp/fileserver/matcher_test.go
@@ -206,9 +206,13 @@ func TestPHPFileMatcher(t *testing.T) {
func TestFirstSplit(t *testing.T) {
m := MatchFile{SplitPath: []string{".php"}}
- actual := m.firstSplit("index.PHP/somewhere")
+ actual, remainder := m.firstSplit("index.PHP/somewhere")
expected := "index.PHP"
+ expectedRemainder := "/somewhere"
if actual != expected {
- t.Errorf("Expected %s but got %s", expected, actual)
+ t.Errorf("Expected split %s but got %s", expected, actual)
+ }
+ if remainder != expectedRemainder {
+ t.Errorf("Expected remainder %s but got %s", expectedRemainder, remainder)
}
}