route
按字面意思和单个单元评估一组指令。
包含在 route 块中的指令不会 在内部重新排序。只有 HTTP 处理程序指令(添加处理程序或中间件到链的指令)可以在 route 块中使用。
此指令是一个特殊情况,因为它的子指令也是常规指令。
语法
route [<matcher>] {
<directives...>
}
- <directives...> 是指令或指令块的列表,每行一个,就像在 route 块之外一样;除了这些指令不会重新排序。只能使用 HTTP 处理程序指令。
实用程序
route
指令在某些高级用例或边缘情况下很有用,可以完全控制 HTTP 处理程序链的部分。
由于 HTTP 中间件评估的顺序很重要,因此 Caddyfile 通常会在解析后重新排序指令,以使 Caddyfile 更易于使用;您不必担心输入内容的顺序。
虽然 内置顺序 与大多数网站兼容,但有时您需要手动控制顺序,无论是针对整个网站还是仅针对其中一部分。这就是 route
指令的作用。
为了说明,考虑两个终止处理程序的情况:redir
和 file_server
。两者都将响应写入客户端,并且不调用链中的下一个处理程序,因此对于某个特定请求,只会执行其中一个。那么哪个先来呢?通常,redir
在 file_server
之前执行,因为通常您只希望在特定情况下发出重定向,并在一般情况下提供文件。
但是,在某些情况下,第二个指令 (redir
) 可能具有比第二个指令 (file_server
) 更具体的匹配器。换句话说,您希望在一般情况下重定向,并且只提供特定文件。
因此,您可能会尝试使用这样的 Caddyfile(但这不会按预期工作!)
example.com {
file_server /specific.html
redir https://anothersite.com{uri}
}
问题是,在 指令排序 后,redir
在 file_server
之前。
但在这种情况下,redir
的匹配器(一个隐式的 *
)是 file_server
的匹配器 (*
是 /specific.html
的超集) 的超集。
幸运的是,解决方案很简单:只需将这两个指令包装在 route
块中,以确保 file_server
在 redir
之前执行
example.com {
route {
file_server /specific.html
redir https://anothersite.com{uri}
}
}
现在 file_server
将在 redir
之前链接,因为顺序是按字面意思取的。
类似指令
还有其他指令可以包装 HTTP 处理程序指令,但每个指令都有其用途,具体取决于您想要传达的行为
-
handle
像route
一样包装其他指令,但有两个区别:1) handle 块彼此互斥,以及 2) handle 内的指令 重新排序 通常。 -
handle_path
与handle
相同,但它在运行其处理程序之前从请求中剥离前缀。 -
handle_errors
类似于handle
,但仅在 Caddy 在请求处理期间遇到错误时才调用。
示例
将对 /api
的请求按原样代理,并将所有其他请求根据它们是否与磁盘上的文件匹配进行重写,否则为 /index.html
。然后提供该文件。
由于 try_files
的指令顺序高于 reverse_proxy
,因此它通常会排序更高并首先运行;这会导致 API 请求全部重写为 /index.html
并无法匹配 /api*
,因此它们都不会被代理,而是会导致来自 file_server
的 404
。将所有内容包装在 route
中可确保 reverse_proxy
始终先运行,在请求被重写之前。
example.com {
root * /srv
route {
reverse_proxy /api* localhost:9000
try_files {path} /index.html
file_server
}
}