文档
一个 项目

handle_errors

设置错误处理程序。

当常规 HTTP 请求处理程序返回错误时,正常处理会停止并调用错误处理程序。错误处理程序形成一条路由,和普通路由完全相同,能够执行普通路由所能做的任何操作。这使得在处理 HTTP 请求错误时能够获得强大的控制力和灵活性。例如,你可以提供静态错误页面、模板化错误页面,或将请求反向代理到另一个后端来处理错误。

该指令可以针对不同的状态码重复使用,以便对不同错误做不同处理。如果未指定状态码,则会匹配任何错误,当其他错误处理程序都不匹配时作为回退。

请求的上下文会被传递到错误路由中,因此在请求上下文中设置的任何值,例如 站点根目录vars,也会在错误处理程序中保留。此外,在处理错误时还可使用 新占位符

注意某些指令,例如可能会写入一个被归类为错误的 HTTP 状态码响应的 reverse_proxy,不会触发错误路由。

你可以使用 error 指令根据自己的路由决策显式触发错误。

语法

handle_errors [<status_codes...>] {
	<directives...>
}
  • <status_codes...> 是要与正在处理的错误匹配的一个或多个 HTTP 状态码。状态码可以是三位数,也可以使用特殊形式 4xx5xx,分别匹配 400-499 或 500-599 范围内的所有状态码。如果未指定状态码,则会匹配任何错误,当其他错误处理程序都不匹配时作为回退。

  • <directives...> 是一行一个的 HTTP 处理器 directivesmatchers 的列表。

占位符

在处理错误时可用以下占位符。它们是 Caddyfile 简写,对应于可以在 HTTP 服务器的错误路由的 JSON 文档 中找到的完整占位符。

Placeholder 说明
{err.status_code} 建议的 HTTP 状态码
{err.status_text} 与建议状态码关联的状态文本
{err.message} 错误信息
{err.trace} 错误来源
{err.id} 该错误发生的标识符

示例

基于状态码的自定义错误页面(例如为 404 错误提供名为 404.html 的页面)。注意在 handle_errors 中运行时,file_server 会保留错误的 HTTP 状态码(假设你事先在站点中设置了 站点根目录):

handle_errors {
	rewrite * /{err.status_code}.html
	file_server
}

使用 templates 写入自定义错误信息的单一错误页面:

handle_errors {
	rewrite * /error.html
	templates
	file_server
}

如果你只想为某些错误码提供自定义错误页面,可以事先使用 file 匹配器检查自定义错误文件是否存在:

handle_errors {
	@custom_err file /err-{err.status_code}.html /err.html
	handle @custom_err {
		rewrite * {file_match.relative}
		file_server
	}
	respond "{err.status_code} {err.status_text}"
}

将请求反向代理到一个更专业、擅长处理 HTTP 错误的服务器以提升你的体验 😸:

handle_errors {
	rewrite * /{err.status_code}
	reverse_proxy https://http.cat {
		header_up Host {upstream_hostport}
		replace_status {err.status_code}
	}
}

简单使用 respond 返回错误代码和名称:

handle_errors {
	respond "{err.status_code} {err.status_text}"
}

为特定错误码做不同处理:

handle_errors 404 410 {
	respond "It's a 404 or 410 error!"
}

handle_errors 5xx {
	respond "It's a 5xx error."
}

handle_errors {
	respond "It's another error"
}

上述行为与下面的配置相同,后者使用 expression 匹配器针对状态码进行匹配,并使用 handle 实现互斥:

handle_errors {
	@404-410 `{err.status_code} in [404, 410]`
	handle @404-410 {
		respond "It's a 404 or 410 error!"
	}

	@5xx `{err.status_code} >= 500 && {err.status_code} < 600`
	handle @5xx {
		respond "It's a 5xx error."
	}

	handle {
		respond "It's another error"
	}
}