diff options
Diffstat (limited to 'modules/caddyhttp/fileserver/matcher.go')
-rw-r--r-- | modules/caddyhttp/fileserver/matcher.go | 45 |
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) ) |