diff --git a/caddyconfig/httpcaddyfile/directives.go b/caddyconfig/httpcaddyfile/directives.go index f411aabe3..e8ad62d22 100644 --- a/caddyconfig/httpcaddyfile/directives.go +++ b/caddyconfig/httpcaddyfile/directives.go @@ -465,6 +465,15 @@ func sortRoutes(routes []ConfigValue, order []string) { return dirPositions[iDir] < dirPositions[jDir] } + // 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; we swap i and j instead of using !, + // so matchers that can't be compared keep their order + if iDir == "vars" { + i, j = j, i + } + // 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 @@ -535,15 +544,7 @@ func sortRoutes(routes []ConfigValue, order []string) { 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 + // most-specific matcher first (or last for vars, see above) return sortByPath }) } diff --git a/caddytest/integration/caddyfile_adapt/map_and_vars_with_raw_types.caddyfiletest b/caddytest/integration/caddyfile_adapt/map_and_vars_with_raw_types.caddyfiletest index 8b872635d..6c9ade715 100644 --- a/caddytest/integration/caddyfile_adapt/map_and_vars_with_raw_types.caddyfiletest +++ b/caddytest/integration/caddyfile_adapt/map_and_vars_with_raw_types.caddyfiletest @@ -101,16 +101,16 @@ vars { ], "source": "{http.request.host}" }, + { + "foo": "bar", + "handler": "vars" + }, { "abc": true, "def": 1, "ghi": 2.3, "handler": "vars", "jkl": "mn op" - }, - { - "foo": "bar", - "handler": "vars" } ] } diff --git a/caddytest/integration/caddyfile_adapt/sort_vars_named_matchers_keep_order.caddyfiletest b/caddytest/integration/caddyfile_adapt/sort_vars_named_matchers_keep_order.caddyfiletest new file mode 100644 index 000000000..724804180 --- /dev/null +++ b/caddytest/integration/caddyfile_adapt/sort_vars_named_matchers_keep_order.caddyfiletest @@ -0,0 +1,63 @@ +:80 + +@first header X-Test a +@second header X-Test a +@third header X-Other b + +vars @first value first +vars @second value second +vars @third value third +---------- +{ + "apps": { + "http": { + "servers": { + "srv0": { + "listen": [ + ":80" + ], + "routes": [ + { + "match": [ + { + "header": { + "X-Test": [ + "a" + ] + } + } + ], + "handle": [ + { + "handler": "vars", + "value": "first" + }, + { + "handler": "vars", + "value": "second" + } + ] + }, + { + "match": [ + { + "header": { + "X-Other": [ + "b" + ] + } + } + ], + "handle": [ + { + "handler": "vars", + "value": "third" + } + ] + } + ] + } + } + } + } +}