aboutsummaryrefslogtreecommitdiffhomepage
path: root/modules/caddyhttp/fileserver/matcher.go
diff options
context:
space:
mode:
Diffstat (limited to 'modules/caddyhttp/fileserver/matcher.go')
-rw-r--r--modules/caddyhttp/fileserver/matcher.go45
1 files changed, 29 insertions, 16 deletions
diff --git a/modules/caddyhttp/fileserver/matcher.go b/modules/caddyhttp/fileserver/matcher.go
index 28f7b89be..c42907491 100644
--- a/modules/caddyhttp/fileserver/matcher.go
+++ b/modules/caddyhttp/fileserver/matcher.go
@@ -173,7 +173,7 @@ func (m *MatchFile) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
func (MatchFile) CELLibrary(ctx caddy.Context) (cel.Library, error) {
requestType := cel.ObjectType("http.Request")
- matcherFactory := func(data ref.Val) (caddyhttp.RequestMatcher, error) {
+ matcherFactory := func(data ref.Val) (caddyhttp.RequestMatcherWithError, error) {
values, err := caddyhttp.CELValueToMapStrList(data)
if err != nil {
return nil, err
@@ -313,12 +313,22 @@ func (m MatchFile) Validate() error {
// - http.matchers.file.type: file or directory
// - http.matchers.file.remainder: Portion remaining after splitting file path (if configured)
func (m MatchFile) Match(r *http.Request) bool {
+ match, err := m.selectFile(r)
+ if err != nil {
+ // nolint:staticcheck
+ caddyhttp.SetVar(r.Context(), caddyhttp.MatcherErrorVarKey, err)
+ }
+ return match
+}
+
+// MatchWithError returns true if r matches m.
+func (m MatchFile) MatchWithError(r *http.Request) (bool, error) {
return m.selectFile(r)
}
// selectFile chooses a file according to m.TryPolicy by appending
// the paths in m.TryFiles to m.Root, with placeholder replacements.
-func (m MatchFile) selectFile(r *http.Request) (matched bool) {
+func (m MatchFile) selectFile(r *http.Request) (bool, error) {
repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
root := filepath.Clean(repl.ReplaceAll(m.Root, "."))
@@ -330,7 +340,7 @@ func (m MatchFile) selectFile(r *http.Request) (matched bool) {
if c := m.logger.Check(zapcore.ErrorLevel, "use of unregistered filesystem"); c != nil {
c.Write(zap.String("fs", fsName))
}
- return false
+ return false, nil
}
type matchCandidate struct {
fullpath, relative, splitRemainder string
@@ -421,15 +431,18 @@ func (m MatchFile) selectFile(r *http.Request) (matched bool) {
switch m.TryPolicy {
case "", tryPolicyFirstExist:
for _, pattern := range m.TryFiles {
+ // If the pattern is a status code, emit an error,
+ // which short-circuits the middleware pipeline and
+ // writes an HTTP error response.
if err := parseErrorCode(pattern); err != nil {
- caddyhttp.SetVar(r.Context(), caddyhttp.MatcherErrorVarKey, err)
- return
+ return false, err
}
+
candidates := makeCandidates(pattern)
for _, c := range candidates {
if info, exists := m.strictFileExists(fileSystem, c.fullpath); exists {
setPlaceholders(c, info)
- return true
+ return true, nil
}
}
}
@@ -450,10 +463,10 @@ func (m MatchFile) selectFile(r *http.Request) (matched bool) {
}
}
if largestInfo == nil {
- return false
+ return false, nil
}
setPlaceholders(largest, largestInfo)
- return true
+ return true, nil
case tryPolicySmallestSize:
var smallestSize int64
@@ -471,10 +484,10 @@ func (m MatchFile) selectFile(r *http.Request) (matched bool) {
}
}
if smallestInfo == nil {
- return false
+ return false, nil
}
setPlaceholders(smallest, smallestInfo)
- return true
+ return true, nil
case tryPolicyMostRecentlyMod:
var recent matchCandidate
@@ -491,13 +504,13 @@ func (m MatchFile) selectFile(r *http.Request) (matched bool) {
}
}
if recentInfo == nil {
- return false
+ return false, nil
}
setPlaceholders(recent, recentInfo)
- return true
+ return true, nil
}
- return
+ return false, nil
}
// parseErrorCode checks if the input is a status
@@ -703,7 +716,7 @@ const (
// Interface guards
var (
- _ caddy.Validator = (*MatchFile)(nil)
- _ caddyhttp.RequestMatcher = (*MatchFile)(nil)
- _ caddyhttp.CELLibraryProducer = (*MatchFile)(nil)
+ _ caddy.Validator = (*MatchFile)(nil)
+ _ caddyhttp.RequestMatcherWithError = (*MatchFile)(nil)
+ _ caddyhttp.CELLibraryProducer = (*MatchFile)(nil)
)