@marcel91200 / caddy Mirror · read-only / commits / 6ae02b5c
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 11, 03:30 UTC

httpcaddyfile: keep source order for vars with non-comparable matchers (#8197)

Use i/j swap instead of !sortByPath for vars, so matchers that can't be compared keep their Caddyfile order. Path matchers still sort with the more specific one later. Fixes the vars ordering part of #8187.

IcyJerry committed Oct 12, 2026 at 18:49 UTC 6ae02b5ccbd9c3ac4c0db2cfc1789cc1ada4e54a
3 files changed +77 -13
caddyconfig/httpcaddyfile/directives.go
+10 -9
@@ -465,6 +465,15 @@ func sortRoutes(routes []ConfigValue, order []string) {
465 return dirPositions[iDir] < dirPositions[jDir]
466 }
467
468 + // some directives involve setting values which can overwrite
469 + // each other, so it makes most sense to reverse the order so
470 + // that the least-specific matcher is first, allowing the last
471 + // matching one to win; we swap i and j instead of using !,
472 + // so matchers that can't be compared keep their order
473 + if iDir == "vars" {
474 + i, j = j, i
475 + }
476 +
477 // directives are the same; sub-sort by path matcher length if there's
478 // only one matcher set and one path (this is a very common case and
479 // usually -- but not always -- helpful/expected, oh well; user can
@@ -535,15 +544,7 @@ func sortRoutes(routes []ConfigValue, order []string) {
544 return len(iRoute.MatcherSetsRaw) > 0 && len(jRoute.MatcherSetsRaw) == 0
545 }()
546
538 - // some directives involve setting values which can overwrite
539 - // each other, so it makes most sense to reverse the order so
540 - // that the least-specific matcher is first, allowing the last
541 - // matching one to win
542 - if iDir == "vars" {
543 - return !sortByPath
544 - }
545 -
546 - // everything else is most-specific matcher first
547 + // most-specific matcher first (or last for vars, see above)
548 return sortByPath
549 })
550 }
caddytest/integration/caddyfile_adapt/map_and_vars_with_raw_types.caddyfiletest
+4 -4
@@ -101,16 +101,16 @@ vars {
101 ],
102 "source": "{http.request.host}"
103 },
104 + {
105 + "foo": "bar",
106 + "handler": "vars"
107 + },
108 {
109 "abc": true,
110 "def": 1,
111 "ghi": 2.3,
112 "handler": "vars",
113 "jkl": "mn op"
110 - },
111 - {
112 - "foo": "bar",
113 - "handler": "vars"
114 }
115 ]
116 }
caddytest/integration/caddyfile_adapt/sort_vars_named_matchers_keep_order.caddyfiletest new
+63
@@ -0,0 +1,63 @@
1 +:80
2 +
3 +@first header X-Test a
4 +@second header X-Test a
5 +@third header X-Other b
6 +
7 +vars @first value first
8 +vars @second value second
9 +vars @third value third
10 +----------
11 +{
12 + "apps": {
13 + "http": {
14 + "servers": {
15 + "srv0": {
16 + "listen": [
17 + ":80"
18 + ],
19 + "routes": [
20 + {
21 + "match": [
22 + {
23 + "header": {
24 + "X-Test": [
25 + "a"
26 + ]
27 + }
28 + }
29 + ],
30 + "handle": [
31 + {
32 + "handler": "vars",
33 + "value": "first"
34 + },
35 + {
36 + "handler": "vars",
37 + "value": "second"
38 + }
39 + ]
40 + },
41 + {
42 + "match": [
43 + {
44 + "header": {
45 + "X-Other": [
46 + "b"
47 + ]
48 + }
49 + }
50 + ],
51 + "handle": [
52 + {
53 + "handler": "vars",
54 + "value": "third"
55 + }
56 + ]
57 + }
58 + ]
59 + }
60 + }
61 + }
62 + }
63 +}