diff options
author | Francis Lavoie <[email protected]> | 2024-10-11 18:59:50 -0400 |
---|---|---|
committer | Francis Lavoie <[email protected]> | 2024-11-04 14:10:51 -0500 |
commit | 565ce58feeb4786747cc3ea37429f97ddfda4c27 (patch) | |
tree | 98ab5627be912fbed874b4de404ee61911f8ecbf | |
parent | 03f463adf2da5a2c740a1c9259a2711a17e30912 (diff) | |
download | caddy-565ce58feeb4786747cc3ea37429f97ddfda4c27.tar.gz caddy-565ce58feeb4786747cc3ea37429f97ddfda4c27.zip |
Looser interface checking to allow fallback
-rw-r--r-- | caddyconfig/httpcaddyfile/httptype.go | 20 | ||||
-rw-r--r-- | modules/caddyhttp/matchers.go | 24 | ||||
-rw-r--r-- | modules/caddyhttp/routes.go | 37 |
3 files changed, 58 insertions, 23 deletions
diff --git a/caddyconfig/httpcaddyfile/httptype.go b/caddyconfig/httpcaddyfile/httptype.go index 704424acb..beee2d1a5 100644 --- a/caddyconfig/httpcaddyfile/httptype.go +++ b/caddyconfig/httpcaddyfile/httptype.go @@ -1466,9 +1466,9 @@ func (st *ServerType) compileEncodedMatcherSets(sblock serverBlock) ([]caddy.Mod // iterate each pairing of host and path matchers and // put them into a map for JSON encoding - var matcherSets []map[string]caddyhttp.RequestMatcher + var matcherSets []map[string]caddyhttp.RequestMatcherWithError for _, mp := range matcherPairs { - matcherSet := make(map[string]caddyhttp.RequestMatcher) + matcherSet := make(map[string]caddyhttp.RequestMatcherWithError) if len(mp.hostm) > 0 { matcherSet["host"] = mp.hostm } @@ -1527,12 +1527,16 @@ func parseMatcherDefinitions(d *caddyfile.Dispenser, matchers map[string]caddy.M if err != nil { return err } - rm, ok := unm.(caddyhttp.RequestMatcher) - if !ok { - return fmt.Errorf("matcher module '%s' is not a request matcher", matcherName) + + if rm, ok := unm.(caddyhttp.RequestMatcherWithError); ok { + matchers[definitionName][matcherName] = caddyconfig.JSON(rm, nil) + return nil } - matchers[definitionName][matcherName] = caddyconfig.JSON(rm, nil) - return nil + if rm, ok := unm.(caddyhttp.RequestMatcher); ok { + matchers[definitionName][matcherName] = caddyconfig.JSON(rm, nil) + return nil + } + return fmt.Errorf("matcher module '%s' is not a request matcher", matcherName) } // if the next token is quoted, we can assume it's not a matcher name @@ -1576,7 +1580,7 @@ func parseMatcherDefinitions(d *caddyfile.Dispenser, matchers map[string]caddy.M return nil } -func encodeMatcherSet(matchers map[string]caddyhttp.RequestMatcher) (caddy.ModuleMap, error) { +func encodeMatcherSet(matchers map[string]caddyhttp.RequestMatcherWithError) (caddy.ModuleMap, error) { msEncoded := make(caddy.ModuleMap) for matcherName, val := range matchers { jsonBytes, err := json.Marshal(val) diff --git a/modules/caddyhttp/matchers.go b/modules/caddyhttp/matchers.go index 427ecf3c9..2197faa70 100644 --- a/modules/caddyhttp/matchers.go +++ b/modules/caddyhttp/matchers.go @@ -1392,7 +1392,15 @@ func (m *MatchNot) Provision(ctx caddy.Context) error { for _, modMap := range matcherSets.([]map[string]any) { var ms MatcherSet for _, modIface := range modMap { - ms = append(ms, modIface.(RequestMatcher)) + if mod, ok := modIface.(RequestMatcherWithError); ok { + ms = append(ms, mod) + continue + } + if mod, ok := modIface.(RequestMatcher); ok { + ms = append(ms, mod) + continue + } + return fmt.Errorf("module is not a request matcher: %T", modIface) } m.MatcherSets = append(m.MatcherSets, ms) } @@ -1536,7 +1544,7 @@ func (mre *MatchRegexp) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { // ParseCaddyfileNestedMatcher parses the Caddyfile tokens for a nested // matcher set, and returns its raw module map value. func ParseCaddyfileNestedMatcherSet(d *caddyfile.Dispenser) (caddy.ModuleMap, error) { - matcherMap := make(map[string]RequestMatcher) + matcherMap := make(map[string]any) // in case there are multiple instances of the same matcher, concatenate // their tokens (we expect that UnmarshalCaddyfile should be able to @@ -1561,11 +1569,15 @@ func ParseCaddyfileNestedMatcherSet(d *caddyfile.Dispenser) (caddy.ModuleMap, er if err != nil { return nil, err } - rm, ok := unm.(RequestMatcher) - if !ok { - return nil, fmt.Errorf("matcher module '%s' is not a request matcher", matcherName) + if rm, ok := unm.(RequestMatcherWithError); ok { + matcherMap[matcherName] = rm + continue + } + if rm, ok := unm.(RequestMatcher); ok { + matcherMap[matcherName] = rm + continue } - matcherMap[matcherName] = rm + return nil, fmt.Errorf("matcher module '%s' is not a request matcher", matcherName) } // we should now have a functional matcher, but we also diff --git a/modules/caddyhttp/routes.go b/modules/caddyhttp/routes.go index 9576070f6..392555c56 100644 --- a/modules/caddyhttp/routes.go +++ b/modules/caddyhttp/routes.go @@ -336,15 +336,26 @@ func wrapMiddleware(ctx caddy.Context, mh MiddlewareHandler, metrics *Metrics) M // MatcherSet is a set of matchers which // must all match in order for the request // to be matched successfully. -type MatcherSet []RequestMatcher +type MatcherSet []any // Match returns true if the request matches all // matchers in mset or if there are no matchers. func (mset MatcherSet) Match(r *http.Request) bool { for _, m := range mset { - if !m.Match(r) { - return false + if me, ok := m.(RequestMatcherWithError); ok { + match, _ := me.MatchWithError(r) + if !match { + return false + } + continue + } + if me, ok := m.(RequestMatcher); ok { + if !me.Match(r) { + return false + } + continue } + return false } return true } @@ -357,8 +368,10 @@ func (mset MatcherSet) MatchWithError(r *http.Request) (bool, error) { if err != nil || !match { return match, err } - } else { - if !m.Match(r) { + continue + } + if me, ok := m.(RequestMatcher); ok { + if !me.Match(r) { // for backwards compatibility err, ok := GetVar(r.Context(), MatcherErrorVarKey).(error) if ok { @@ -368,7 +381,9 @@ func (mset MatcherSet) MatchWithError(r *http.Request) (bool, error) { } return false, nil } + continue } + return false, fmt.Errorf("matcher is not a RequestMatcher or RequestMatcherWithError: %#v", m) } return true, nil } @@ -401,11 +416,15 @@ func (ms *MatcherSets) FromInterface(matcherSets any) error { for _, matcherSetIfaces := range matcherSets.([]map[string]any) { var matcherSet MatcherSet for _, matcher := range matcherSetIfaces { - reqMatcher, ok := matcher.(RequestMatcher) - if !ok { - return fmt.Errorf("decoded module is not a RequestMatcher: %#v", matcher) + if m, ok := matcher.(RequestMatcherWithError); ok { + matcherSet = append(matcherSet, m) + continue + } + if m, ok := matcher.(RequestMatcher); ok { + matcherSet = append(matcherSet, m) + continue } - matcherSet = append(matcherSet, reqMatcher) + return fmt.Errorf("decoded module is not a RequestMatcher or RequestMatcherWithError: %#v", matcher) } *ms = append(*ms, matcherSet) } |