summaryrefslogtreecommitdiff
path: root/caddyconfig/httpcaddyfile
diff options
context:
space:
mode:
authorMatthew Holt <mholt@users.noreply.github.com>2022-09-13 13:43:21 -0600
committerMatthew Holt <mholt@users.noreply.github.com>2022-09-13 13:43:21 -0600
commit754fe4f7b4dddbfc7a8ee7fee405cee057da858e (patch)
tree56fd84493e7a076f649c3c5d5fc5474707e72aad /caddyconfig/httpcaddyfile
parent20d487be573424e7647b5a157754f6e284554e23 (diff)
httpcaddyfile: Fix sorting of repeated directives
Fixes #5037
Diffstat (limited to 'caddyconfig/httpcaddyfile')
-rw-r--r--caddyconfig/httpcaddyfile/directives.go43
-rw-r--r--caddyconfig/httpcaddyfile/httptype.go2
2 files changed, 26 insertions, 19 deletions
diff --git a/caddyconfig/httpcaddyfile/directives.go b/caddyconfig/httpcaddyfile/directives.go
index 89706b3..e2113eb 100644
--- a/caddyconfig/httpcaddyfile/directives.go
+++ b/caddyconfig/httpcaddyfile/directives.go
@@ -406,7 +406,7 @@ func sortRoutes(routes []ConfigValue) {
return false
}
- // decode the path matchers, if there is just one of them
+ // decode the path matchers if there is just one matcher set
var iPM, jPM caddyhttp.MatchPath
if len(iRoute.MatcherSetsRaw) == 1 {
_ = json.Unmarshal(iRoute.MatcherSetsRaw[0]["path"], &iPM)
@@ -415,38 +415,45 @@ func sortRoutes(routes []ConfigValue) {
_ = json.Unmarshal(jRoute.MatcherSetsRaw[0]["path"], &jPM)
}
- // sort by longer path (more specific) first; missing path
- // matchers or multi-matchers are treated as zero-length paths
+ // if there is only one path in the path matcher, sort by longer path
+ // (more specific) first; missing path matchers or multi-matchers are
+ // treated as zero-length paths
var iPathLen, jPathLen int
- if len(iPM) > 0 {
+ if len(iPM) == 1 {
iPathLen = len(iPM[0])
}
- if len(jPM) > 0 {
+ if len(jPM) == 1 {
jPathLen = len(jPM[0])
}
// some directives involve setting values which can overwrite
- // eachother, so it makes most sense to reverse the order so
+ // 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" {
- // if both directives have no path matcher, use whichever one
- // has no matcher first.
- if iPathLen == 0 && jPathLen == 0 {
- return len(iRoute.MatcherSetsRaw) == 0 && len(jRoute.MatcherSetsRaw) > 0
+ // 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
}
- // sort with the least-specific (shortest) path first
- 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 {
- // if both directives have no path matcher, use whichever one
- // has any kind of matcher defined first.
- if iPathLen == 0 && jPathLen == 0 {
- return len(iRoute.MatcherSetsRaw) > 0 && len(jRoute.MatcherSetsRaw) == 0
+ // 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
}
- // sort with the most-specific (longest) path first
- return iPathLen > jPathLen
+ // if both directives don't have a single path to compare,
+ // 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
}
})
}
diff --git a/caddyconfig/httpcaddyfile/httptype.go b/caddyconfig/httpcaddyfile/httptype.go
index 72d98bd..9cf386a 100644
--- a/caddyconfig/httpcaddyfile/httptype.go
+++ b/caddyconfig/httpcaddyfile/httptype.go
@@ -955,7 +955,7 @@ func appendSubrouteToRouteList(routeList caddyhttp.RouteList,
func buildSubroute(routes []ConfigValue, groupCounter counter) (*caddyhttp.Subroute, error) {
for _, val := range routes {
if !directiveIsOrdered(val.directive) {
- return nil, fmt.Errorf("directive '%s' is not ordered, so it cannot be used here", val.directive)
+ return nil, fmt.Errorf("directive '%s' is not an ordered HTTP handler, so it cannot be used here", val.directive)
}
}