diff options
author | Francis Lavoie <lavofr@gmail.com> | 2023-03-27 15:43:44 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-27 15:43:44 -0400 |
commit | 330be2d8c793147d3914f944eecb96c18f2eabff (patch) | |
tree | 87003a6af2df30d146cd0487657362489edd908e /caddyconfig/httpcaddyfile | |
parent | 0cc49c053f77bf6efa8107fa50d2e256a91d0ff8 (diff) |
httpcaddyfile: Adjust path matcher sorting to solve for specificity (#5462)
Diffstat (limited to 'caddyconfig/httpcaddyfile')
-rw-r--r-- | caddyconfig/httpcaddyfile/directives.go | 33 |
1 files changed, 17 insertions, 16 deletions
diff --git a/caddyconfig/httpcaddyfile/directives.go b/caddyconfig/httpcaddyfile/directives.go index a772dba..b8faa4a 100644 --- a/caddyconfig/httpcaddyfile/directives.go +++ b/caddyconfig/httpcaddyfile/directives.go @@ -427,26 +427,16 @@ func sortRoutes(routes []ConfigValue) { jPathLen = len(jPM[0]) } - // some directives involve setting values which can overwrite - // each other, so it makes most sense to reverse the order so - // that the lease specific matcher is first; everything else - // has most-specific matcher first - if iDir == "vars" { + sortByPath := func() bool { // we can only confidently compare path lengths if both // directives have a single path to match (issue #5037) if iPathLen > 0 && jPathLen > 0 { - // sort least-specific (shortest) path first - return iPathLen < jPathLen - } + // if both paths are the same except for a trailing wildcard, + // sort by the shorter path first (which is more specific) + if strings.TrimSuffix(iPM[0], "*") == strings.TrimSuffix(jPM[0], "*") { + return iPathLen < jPathLen + } - // if both directives don't have a single path to compare, - // sort whichever one has no matcher first; if both have - // no matcher, sort equally (stable sort preserves order) - return len(iRoute.MatcherSetsRaw) == 0 && len(jRoute.MatcherSetsRaw) > 0 - } else { - // we can only confidently compare path lengths if both - // directives have a single path to match (issue #5037) - if iPathLen > 0 && jPathLen > 0 { // sort most-specific (longest) path first return iPathLen > jPathLen } @@ -455,7 +445,18 @@ func sortRoutes(routes []ConfigValue) { // sort whichever one has a matcher first; if both have // a matcher, sort equally (stable sort preserves order) return len(iRoute.MatcherSetsRaw) > 0 && len(jRoute.MatcherSetsRaw) == 0 + }() + + // some directives involve setting values which can overwrite + // each other, so it makes most sense to reverse the order so + // that the least-specific matcher is first, allowing the last + // matching one to win + if iDir == "vars" { + return !sortByPath } + + // everything else is most-specific matcher first + return sortByPath }) } |