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
}
}