Caddy 请求头匹配正确仍落到 respond:检查指令执行顺序
请求头匹配正确,Caddy 却始终返回固定拒绝提示时,检查适配后的指令顺序。用 handle 互斥分支或 route 明确顺序,并验证允许、拒绝和上游路径。
Caddyfile 已把 reverse_proxy @api 写在前面,末尾用 respond 返回拒绝提示。请求携带了正确的匹配头,却始终收到这个提示,上游没有对应访问记录。对于 Caddy 2,先检查适配后的处理顺序:文件里先写哪一行,不等于先执行哪一个处理器。
普通站点块默认会把 respond 排在 reverse_proxy 前。没有 matcher 的 respond 匹配所有请求,并直接写出响应,后面的代理就不会处理这次请求。这与请求头值写错不同,也不能据此认定后端连接失败。
先确认返回提示的是哪个处理器
对照响应内容、Caddy 的有效配置和上游访问记录。如果正好返回配置里的固定提示,而对应时间上游没有收到请求,应检查默认排序与匹配范围。
还要核对实际请求头名称和值,以及客户端是否先发生了跳转。浏览器跨域请求或重定向后的请求,未必保留最初准备的字段。诊断时不要把真实令牌写进共享命令、访问日志或截图。
下面是会出现该顺序问题的结构示例;demo-only 只是演示匹配值,不应用作正式访问凭据:
app.example.com {
@api header X-Route demo-only
reverse_proxy @api 127.0.0.1:5000
respond "Not allowed" 403
}
这里把 proxy 移到文件顶部也没有作用。不同指令仍按默认顺序排列,而固定响应会先结束请求。
用 handle 表达匹配分支与默认分支
只有匹配请求交给上游,其他请求返回拒绝时,可用同级互斥的 handle 块:
app.example.com {
@api header X-Route demo-only
handle @api {
reverse_proxy 127.0.0.1:5000
}
handle {
respond "Not allowed" 403
}
}
这是结构示例,域名、判断条件和上游地址要按实际部署替换。无 matcher 的 handle 是默认分支,只有前面的匹配分支没有选中才使用它。handle 内部的指令仍按通常规则排序,并不是整个文件从此逐行执行。
如果必须保留指定处理器顺序,也可把相关部分放入 route:
app.example.com {
@api header X-Route demo-only
route {
reverse_proxy @api 127.0.0.1:5000
respond "Not allowed" 403
}
}
route 内部保留书写顺序。匹配请求由代理处理;不匹配时继续到固定响应。只将确实需要控制顺序的部分放入 route,并核对认证、重写等既有处理器的位置。站点地址与其他非 HTTP 处理指令不能任意塞进该块。
这两种配置按需要选一种即可。修改全局 order 会影响其他站点的同类指令,单个站点的分支问题通常无须扩大到全局。
验证允许与拒绝两条路径
修改前保留 Caddyfile 和当前加载方式。在本机隔离环境检查配置及适配结果,确认操作针对真正运行的实例;容器里的回环地址也不能用于访问另一容器。
加载配置后,匹配请求应到达预期上游,并获得该服务的实际响应;不匹配请求应仍被拒绝。再检查既有认证、其他站点和接口,不能只以某一条请求变成 200 作为全部验收。
若匹配路径现在返回 502,说明已进入代理连接阶段,应按实际上游地址与日志继续排查。固定拒绝提示消失不代表后端已经可用。需要回退时恢复原配置并按相同方式校验、加载,确认没有意外开放默认分支。


