diff options
Diffstat (limited to 'caddyconfig/httpcaddyfile')
-rw-r--r-- | caddyconfig/httpcaddyfile/directives.go | 74 |
1 files changed, 33 insertions, 41 deletions
diff --git a/caddyconfig/httpcaddyfile/directives.go b/caddyconfig/httpcaddyfile/directives.go index ff248bf..ac401e1 100644 --- a/caddyconfig/httpcaddyfile/directives.go +++ b/caddyconfig/httpcaddyfile/directives.go @@ -276,53 +276,45 @@ func sortRoutes(routes []ConfigValue) { dirPositions[dir] = i } - // while we are sorting, we will need to decode a route's path matcher - // in order to sub-sort by path length; we can amortize this operation - // for efficiency by storing the decoded matchers in a slice - decodedMatchers := make([]caddyhttp.MatchPath, len(routes)) - sort.SliceStable(routes, func(i, j int) bool { + // if the directives are different, just use the established directive order iDir, jDir := routes[i].directive, routes[j].directive - if iDir == jDir { - // directives are the same; sub-sort by path matcher length - // if there's only one matcher set and one path (common case) - iRoute, ok := routes[i].Value.(caddyhttp.Route) - if !ok { - return false - } - jRoute, ok := routes[j].Value.(caddyhttp.Route) - if !ok { - return false - } + if iDir != jDir { + return dirPositions[iDir] < dirPositions[jDir] + } - // use already-decoded matcher, or decode if it's the first time seeing it - iPM, jPM := decodedMatchers[i], decodedMatchers[j] - if iPM == nil && len(iRoute.MatcherSetsRaw) == 1 { - var pathMatcher caddyhttp.MatchPath - _ = json.Unmarshal(iRoute.MatcherSetsRaw[0]["path"], &pathMatcher) - decodedMatchers[i] = pathMatcher - iPM = pathMatcher - } - if jPM == nil && len(jRoute.MatcherSetsRaw) == 1 { - var pathMatcher caddyhttp.MatchPath - _ = json.Unmarshal(jRoute.MatcherSetsRaw[0]["path"], &pathMatcher) - decodedMatchers[j] = pathMatcher - jPM = pathMatcher - } + // directives are the same; sub-sort by path matcher length if there's + // only one matcher set and one path (this is a very common case and + // usually -- but not always -- helpful/expected, oh well; user can + // always take manual control of order using handler or route blocks) + iRoute, ok := routes[i].Value.(caddyhttp.Route) + if !ok { + return false + } + jRoute, ok := routes[j].Value.(caddyhttp.Route) + if !ok { + return false + } - // sort by longer path (more specific) first; missing - // path matchers are treated as zero-length paths - var iPathLen, jPathLen int - if iPM != nil { - iPathLen = len(iPM[0]) - } - if jPM != nil { - jPathLen = len(jPM[0]) - } - return iPathLen > jPathLen + // decode the path matchers, if there is just one of them + var iPM, jPM caddyhttp.MatchPath + if len(iRoute.MatcherSetsRaw) == 1 { + _ = json.Unmarshal(iRoute.MatcherSetsRaw[0]["path"], &iPM) + } + if len(jRoute.MatcherSetsRaw) == 1 { + _ = json.Unmarshal(jRoute.MatcherSetsRaw[0]["path"], &jPM) } - return dirPositions[iDir] < dirPositions[jDir] + // 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 { + iPathLen = len(iPM[0]) + } + if len(jPM) > 0 { + jPathLen = len(jPM[0]) + } + return iPathLen > jPathLen }) } |