DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

Caddy 第二行 expression 没生效

Caddy 2.11.7 的命名匹配器重复写 expression 时可能只保留第一行。将条件放入一份 CEL 表达式,检查适配 JSON 和应拒绝的请求。

Caddy 的命名匹配器先用 expression 限制 GET,再用另一行 expression 限制 /public/ 路径,结果 GET 请求仍能访问原本不应匹配的路径。先检查适配后的 JSON:Caddy 2.11.7 会只保留第一行表达式,第二行没有进入配置。

这与原生 JSON 中多个匹配器集合按 OR 判断不同。这里是 Caddyfile 中同一个匹配器集合重复写了 expression,表达式模块没有继续读取后面的段落。

把需要同时成立的条件写进一份表达式

以下写法容易误判为两个条件都会生效:

@public {
    expression {method} == 'GET'
    expression {path}.startsWith('/public/')
}

在受影响版本中,第一行已被读取,后面的路径条件被忽略。其他类型的匹配器有各自的合并规则,不能用它们的表现推断重复 expression 一定会被 AND 连接。

需要方法和路径同时满足时,明确写成一份 CEL 表达式:

@public expression {method} == 'GET' && {path}.startsWith('/public/')

多个逻辑分支应加上与策略相符的括号;需要任选一个条件时才用 ||。不要因为这里使用 &&,就把原有 OR 策略也一起改掉。

表达式太长可以用 Caddyfile 支持的 heredoc,把换行留在同一份表达式中:

@public <<CEL
    {method} == 'GET'
    && {path}.startsWith('/public/')
CEL

这仍是一个匹配器,不是两行独立的 expression。若原配置还有 not,还要保留它对整个条件的否定范围;只拼接字符串而忽略括号,可能改变访问规则。

检查最终 JSON,也检查不该放行的请求

记录实际 Caddy 版本,保存原配置,在本机或已有隔离环境中适配并校验副本。查看命名匹配器最终生成的表达式,确认方法、路径和其他必要条件都还在。配置中可能带有认证值,副本及适配结果应限制访问,不要直接贴到公开日志。

再通过受控请求验证组合:GET /public/a.txt 应进入目标处理器,GET /private/a.txt 与 POST /public/a.txt 则应保持原策略规定的拒绝结果。示例路径只表达判断关系,实际请求应选用没有业务写入副作用的端点。

如果适配结果已经包含全部条件,请继续检查处理器、兜底路由和实际加载的配置。请求进入错误路由还有其他原因,不能把每次路径匹配异常都归到重复表达式。

后续修复会拒绝重复写法

截至 2026 年 10 月 14 日,针对这一问题的修复已经合入源码,处理方式是拒绝重复的 expression,并提示在一份表达式内显式组合条件。它不会替配置作者自动选择 AND 或 OR。已核对的稳定版 2.11.7 仍采用旧解析分支。

因此无论是否计划升级,都应先把条件表达清楚。修改访问规则前保留旧配置,再按原有方式加载;验证正常请求与拒绝请求的结果,不能只以配置校验成功为依据。

若出现新的路由回归,恢复保存的配置并重新核对生效入口。涉及访问控制时应保留原本的拒绝保护,不要通过删除整个匹配器来消除解析错误。