mirror of
https://github.com/caddyserver/caddy.git
synced 2025-02-24 16:59:00 +01:00
httpcaddyfile: Fix route ordering bug
https://caddy.community/t/cant-get-simple-alias-to-work/7911/8?u=matt This removes an optimization where we amortized path matcher decoding. The decoded matchers were index by... position... which obviously changes during sorting. Duh. Anyway, sorting is sliiightly slower now but the Caddyfile is not really CPU-sensitive, so this is fine.
This commit is contained in:
parent
8dbc5f70a5
commit
cd9317e5df
1 changed files with 35 additions and 43 deletions
|
@ -276,16 +276,17 @@ func sortRoutes(routes []ConfigValue) {
|
||||||
dirPositions[dir] = i
|
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 {
|
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
|
iDir, jDir := routes[i].directive, routes[j].directive
|
||||||
if iDir == jDir {
|
if iDir != jDir {
|
||||||
// directives are the same; sub-sort by path matcher length
|
return dirPositions[iDir] < dirPositions[jDir]
|
||||||
// if there's only one matcher set and one path (common case)
|
}
|
||||||
|
|
||||||
|
// 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)
|
iRoute, ok := routes[i].Value.(caddyhttp.Route)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
|
@ -295,34 +296,25 @@ func sortRoutes(routes []ConfigValue) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// use already-decoded matcher, or decode if it's the first time seeing it
|
// decode the path matchers, if there is just one of them
|
||||||
iPM, jPM := decodedMatchers[i], decodedMatchers[j]
|
var iPM, jPM caddyhttp.MatchPath
|
||||||
if iPM == nil && len(iRoute.MatcherSetsRaw) == 1 {
|
if len(iRoute.MatcherSetsRaw) == 1 {
|
||||||
var pathMatcher caddyhttp.MatchPath
|
_ = json.Unmarshal(iRoute.MatcherSetsRaw[0]["path"], &iPM)
|
||||||
_ = json.Unmarshal(iRoute.MatcherSetsRaw[0]["path"], &pathMatcher)
|
|
||||||
decodedMatchers[i] = pathMatcher
|
|
||||||
iPM = pathMatcher
|
|
||||||
}
|
}
|
||||||
if jPM == nil && len(jRoute.MatcherSetsRaw) == 1 {
|
if len(jRoute.MatcherSetsRaw) == 1 {
|
||||||
var pathMatcher caddyhttp.MatchPath
|
_ = json.Unmarshal(jRoute.MatcherSetsRaw[0]["path"], &jPM)
|
||||||
_ = json.Unmarshal(jRoute.MatcherSetsRaw[0]["path"], &pathMatcher)
|
|
||||||
decodedMatchers[j] = pathMatcher
|
|
||||||
jPM = pathMatcher
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort by longer path (more specific) first; missing
|
// sort by longer path (more specific) first; missing path
|
||||||
// path matchers are treated as zero-length paths
|
// matchers or multi-matchers are treated as zero-length paths
|
||||||
var iPathLen, jPathLen int
|
var iPathLen, jPathLen int
|
||||||
if iPM != nil {
|
if len(iPM) > 0 {
|
||||||
iPathLen = len(iPM[0])
|
iPathLen = len(iPM[0])
|
||||||
}
|
}
|
||||||
if jPM != nil {
|
if len(jPM) > 0 {
|
||||||
jPathLen = len(jPM[0])
|
jPathLen = len(jPM[0])
|
||||||
}
|
}
|
||||||
return iPathLen > jPathLen
|
return iPathLen > jPathLen
|
||||||
}
|
|
||||||
|
|
||||||
return dirPositions[iDir] < dirPositions[jDir]
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue