mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-27 06:03:48 +03:00
httpcaddyfile: Adjust path matcher sorting to solve for specificity (#5462)
This commit is contained in:
parent
0cc49c053f
commit
330be2d8c7
4 changed files with 82 additions and 29 deletions
|
@ -427,26 +427,16 @@ func sortRoutes(routes []ConfigValue) {
|
|||
jPathLen = len(jPM[0])
|
||||
}
|
||||
|
||||
// some directives involve setting values which can overwrite
|
||||
// each other, so it makes most sense to reverse the order so
|
||||
// that the lease specific matcher is first; everything else
|
||||
// has most-specific matcher first
|
||||
if iDir == "vars" {
|
||||
sortByPath := func() bool {
|
||||
// we can only confidently compare path lengths if both
|
||||
// directives have a single path to match (issue #5037)
|
||||
if iPathLen > 0 && jPathLen > 0 {
|
||||
// sort least-specific (shortest) path first
|
||||
return iPathLen < jPathLen
|
||||
}
|
||||
// if both paths are the same except for a trailing wildcard,
|
||||
// sort by the shorter path first (which is more specific)
|
||||
if strings.TrimSuffix(iPM[0], "*") == strings.TrimSuffix(jPM[0], "*") {
|
||||
return iPathLen < jPathLen
|
||||
}
|
||||
|
||||
// if both directives don't have a single path to compare,
|
||||
// sort whichever one has no matcher first; if both have
|
||||
// no matcher, sort equally (stable sort preserves order)
|
||||
return len(iRoute.MatcherSetsRaw) == 0 && len(jRoute.MatcherSetsRaw) > 0
|
||||
} else {
|
||||
// we can only confidently compare path lengths if both
|
||||
// directives have a single path to match (issue #5037)
|
||||
if iPathLen > 0 && jPathLen > 0 {
|
||||
// sort most-specific (longest) path first
|
||||
return iPathLen > jPathLen
|
||||
}
|
||||
|
@ -455,7 +445,18 @@ func sortRoutes(routes []ConfigValue) {
|
|||
// sort whichever one has a matcher first; if both have
|
||||
// a matcher, sort equally (stable sort preserves order)
|
||||
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
|
||||
return sortByPath
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -100,16 +100,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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
*.example.com {
|
||||
@foo host foo.example.com
|
||||
handle @foo {
|
||||
handle_path /strip* {
|
||||
handle_path /strip {
|
||||
respond "this should be first"
|
||||
}
|
||||
handle {
|
||||
handle_path /strip* {
|
||||
respond "this should be second"
|
||||
}
|
||||
handle {
|
||||
respond "this should be last"
|
||||
}
|
||||
}
|
||||
handle {
|
||||
respond "this should be last"
|
||||
|
@ -35,13 +38,13 @@
|
|||
"handler": "subroute",
|
||||
"routes": [
|
||||
{
|
||||
"group": "group5",
|
||||
"group": "group6",
|
||||
"handle": [
|
||||
{
|
||||
"handler": "subroute",
|
||||
"routes": [
|
||||
{
|
||||
"group": "group2",
|
||||
"group": "group3",
|
||||
"handle": [
|
||||
{
|
||||
"handler": "subroute",
|
||||
|
@ -68,17 +71,25 @@
|
|||
"match": [
|
||||
{
|
||||
"path": [
|
||||
"/strip*"
|
||||
"/strip"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "group2",
|
||||
"group": "group3",
|
||||
"handle": [
|
||||
{
|
||||
"handler": "subroute",
|
||||
"routes": [
|
||||
{
|
||||
"handle": [
|
||||
{
|
||||
"handler": "rewrite",
|
||||
"strip_path_prefix": "/strip"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"handle": [
|
||||
{
|
||||
|
@ -89,6 +100,31 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"match": [
|
||||
{
|
||||
"path": [
|
||||
"/strip*"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "group3",
|
||||
"handle": [
|
||||
{
|
||||
"handler": "subroute",
|
||||
"routes": [
|
||||
{
|
||||
"handle": [
|
||||
{
|
||||
"body": "this should be last",
|
||||
"handler": "static_response"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -103,7 +139,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"group": "group5",
|
||||
"group": "group6",
|
||||
"handle": [
|
||||
{
|
||||
"handler": "subroute",
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
:80
|
||||
|
||||
vars /foobar foo last
|
||||
vars /foo foo middle
|
||||
vars /foo foo middle-last
|
||||
vars /foo* foo middle-first
|
||||
vars * foo first
|
||||
----------
|
||||
{
|
||||
|
@ -21,6 +22,21 @@ vars * foo first
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
"path": [
|
||||
"/foo*"
|
||||
]
|
||||
}
|
||||
],
|
||||
"handle": [
|
||||
{
|
||||
"foo": "middle-first",
|
||||
"handler": "vars"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"match": [
|
||||
{
|
||||
|
@ -31,7 +47,7 @@ vars * foo first
|
|||
],
|
||||
"handle": [
|
||||
{
|
||||
"foo": "middle",
|
||||
"foo": "middle-last",
|
||||
"handler": "vars"
|
||||
}
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue