MCPcopy
hub / github.com/caddyserver/caddy / MatchWithError

Method MatchWithError

modules/caddyhttp/matchers.go:429–543  ·  view source on GitHub ↗

MatchWithError returns true if r matches m.

(r *http.Request)

Source from the content-addressed store, hash-verified

427
428// MatchWithError returns true if r matches m.
429func (m MatchPath) MatchWithError(r *http.Request) (bool, error) {
430 // Even though RFC 9110 says that path matching is case-sensitive
431 // (https://www.rfc-editor.org/rfc/rfc9110.html#section-4.2.3),
432 // we do case-insensitive matching to mitigate security issues
433 // related to differences between operating systems, applications,
434 // etc; if case-sensitive matching is needed, the regex matcher
435 // can be used instead.
436 reqPath := strings.ToLower(r.URL.Path)
437
438 if runtime.GOOS == "windows" { // issue #5613
439 // Windows treats backslashes as path separators and
440 // ignores trailing dots and spaces when accessing files
441 // (sigh), potentially causing a security risk (cry) if
442 // protected files are not matched as intended.
443 reqPath = strings.ReplaceAll(reqPath, `\`, "/")
444 reqPath = strings.TrimRight(reqPath, ". ")
445 }
446
447 repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
448
449 for _, matchPattern := range m {
450 matchPattern = repl.ReplaceAll(matchPattern, "")
451
452 // special case: whole path is wildcard; this is unnecessary
453 // as it matches all requests, which is the same as no matcher
454 if matchPattern == "*" {
455 return true, nil
456 }
457
458 // Clean the path, merge doubled slashes, etc.
459 // This ensures maliciously crafted requests can't bypass
460 // the path matcher. See #4407. Good security posture
461 // requires that we should do all we can to reduce any
462 // funny-looking paths into "normalized" forms such that
463 // weird variants can't sneak by.
464 //
465 // How we clean the path depends on the kind of pattern:
466 // we either merge slashes or we don't. If the pattern
467 // has double slashes, we preserve them in the path.
468 //
469 // TODO: Despite the fact that the *vast* majority of path
470 // matchers have only 1 pattern, a possible optimization is
471 // to remember the cleaned form of the path for future
472 // iterations; it's just that the way we clean depends on
473 // the kind of pattern.
474
475 mergeSlashes := !strings.Contains(matchPattern, "//")
476
477 // if '%' appears in the match pattern, we interpret that to mean
478 // the intent is to compare that part of the path in raw/escaped
479 // space; i.e. "%40"=="%40", not "@", and "%2F"=="%2F", not "/"
480 if strings.Contains(matchPattern, "%") {
481 escapedPath := r.URL.EscapedPath()
482 if runtime.GOOS == "windows" {
483 escapedPath = windowsEscapedPathSeparatorRepl.Replace(escapedPath)
484 matchPattern = windowsEscapedPathSeparatorRepl.Replace(matchPattern)
485 }
486 reqPathForPattern := CleanPath(escapedPath, mergeSlashes)

Callers 1

MatchMethod · 0.95

Calls 5

CleanPathFunction · 0.85
ReplaceAllMethod · 0.80
MatchMethod · 0.65
ValueMethod · 0.45

Tested by

no test coverage detected