文档
一个 项目

route

将一组指令按字面意义作为一个单元进行评估。

route 块中包含的指令不会被内部重新排序。 只有 HTTP 处理程序指令(将处理程序或中间件添加到链中的指令)才能在 route 块中使用。

此指令是一个特殊情况,因为它的子指令也是常规指令。

语法

route [<matcher>] {
	<directives...>
}
  • <directives...> 是指令或指令块的列表,每行一个,就像在 route 块外部一样; 除非这些指令不会被重新排序。 只能使用 HTTP 处理程序指令。

用途

route 指令在某些高级用例或边缘情况下很有用,可以完全控制 HTTP 处理程序链的某些部分。

由于 HTTP 中间件评估的顺序非常重要,Caddyfile 通常会在解析后重新排序指令,以使 Caddyfile 更易于使用; 您不必担心键入内容的顺序。

虽然内置顺序与大多数站点兼容,但有时您需要手动控制顺序,无论是对于整个站点还是仅对于其中的一部分。 这就是 route 指令的用途。

为了说明这一点,请考虑两个终止处理程序的情况:redirfile_server。 两者都将响应写入客户端,并且不调用链中的下一个处理程序,因此对于特定请求,只会执行其中一个。 那么哪个先执行? 通常,redirfile_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_serverredir 之前执行

example.com {
	route {
		file_server /specific.html
		redir https://anothersite.com{uri}
	}
}

现在 file_server 将在 redir 之前链接,因为顺序是按字面意义理解的。

类似指令

还有其他指令可以包装 HTTP 处理程序指令,但每个指令都有其用途,具体取决于您要表达的行为

  • handleroute 一样包装其他指令,但有两个区别: 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
	}
}