diff options
Diffstat (limited to 'caddyconfig/httpcaddyfile/directives.go')
-rw-r--r-- | caddyconfig/httpcaddyfile/directives.go | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/caddyconfig/httpcaddyfile/directives.go b/caddyconfig/httpcaddyfile/directives.go index 19ecb26..50e27d6 100644 --- a/caddyconfig/httpcaddyfile/directives.go +++ b/caddyconfig/httpcaddyfile/directives.go @@ -16,6 +16,7 @@ package httpcaddyfile import ( "encoding/json" + "sort" "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig" @@ -197,6 +198,48 @@ type ConfigValue struct { directive string } +func sortRoutes(handlers []ConfigValue, dirPositions map[string]int) { + // 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(handlers)) + + sort.SliceStable(handlers, func(i, j int) bool { + iDir, jDir := handlers[i].directive, handlers[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 := handlers[i].Value.(caddyhttp.Route) + jRoute := handlers[j].Value.(caddyhttp.Route) + + if len(iRoute.MatcherSetsRaw) == 1 && len(jRoute.MatcherSetsRaw) == 1 { + // use already-decoded matcher, or decode if it's the first time seeing it + iPM, jPM := decodedMatchers[i], decodedMatchers[j] + if iPM == nil { + var pathMatcher caddyhttp.MatchPath + _ = json.Unmarshal(iRoute.MatcherSetsRaw[0]["path"], &pathMatcher) + decodedMatchers[i] = pathMatcher + iPM = pathMatcher + } + if jPM == nil { + var pathMatcher caddyhttp.MatchPath + _ = json.Unmarshal(jRoute.MatcherSetsRaw[0]["path"], &pathMatcher) + decodedMatchers[j] = pathMatcher + jPM = pathMatcher + } + + // if there is only one path in the matcher, sort by + // longer path (more specific) first + if len(iPM) == 1 && len(jPM) == 1 { + return len(iPM[0]) > len(jPM[0]) + } + } + } + + return dirPositions[iDir] < dirPositions[jDir] + }) +} + // serverBlock pairs a Caddyfile server block // with a "pile" of config values, keyed by class // name. |