errordocument 指令按 http 状态码拦截错误,需在 virtualhost 内配置、路径以/开头、文件真实存在且≥512字节;不支持按路由过滤,路由级处理需结合 location/directory、后端状态码控制或 mod_rewrite。

直接在 <virtualhost></virtualhost> 块里用 ErrorDocument 指令就能拦截特定状态码的错误,但它不按“路由”拦截,而是按 HTTP 状态码拦截——比如 404 是请求路径不存在,500 是服务器内部出错。所谓“拦截特定路由的错误”,本质是让某个路径触发对应状态码后,由你指定的页面响应。
关键不是写路径条件,而是确保:
- 错误真实发生(如访问
/api/user/999返回 404) -
ErrorDocument配置正确,Apache 才会接管
✅ 正确配置 ErrorDocument 的基本要求
- 路径必须以
/开头,是相对于DocumentRoot的 URI(不是文件系统路径) - 对应文件必须真实存在,且 Apache 进程(如
www-data)有读取权限 - 文件内容不能太短(建议 ≥512 字节),否则部分浏览器会忽略自定义页、显示默认提示
- 必须放在
<virtualhost></virtualhost>块内,避免被全局配置覆盖
例如:
<virtualhost>
ServerName example.com
DocumentRoot /var/www/html
ErrorDocument 404 /errors/404.html
ErrorDocument 500 /errors/500.php
ErrorDocument 403 /errors/forbidden.html
</virtualhost>
对应文件需放在 /var/www/html/errors/404.html 等位置。
? 常见误区:想“只对某条路由生效”?
ErrorDocument 本身不支持按 URL 路径过滤(比如“仅 /admin/* 出错时才用 A 页面”)。它对整个虚拟主机生效。
若真要实现路由级差异化错误处理,得靠组合手段:
-
用
<location></location>或<directory></directory>套一层作用域(有限支持)<location> ErrorDocument 404 /errors/admin-404.html </location>⚠️ 注意:Apache 2.4+ 中
ErrorDocument在<location></location>内可能不生效,推荐改用<directory></directory>或统一在<virtualhost></virtualhost>里配,再靠后端逻辑区分。 -
让后端主动返回特定状态码 + 统一 ErrorDocument
比如/api/*接口出错时,后端返回502或503,你在 VirtualHost 里单独配:ErrorDocument 502 /errors/api-gateway-down.html ErrorDocument 503 /errors/api-maintenance.html
-
用 mod_rewrite 拦截路径并主动触发错误(进阶)
如果希望/legacy/*访问全部返回 410(Gone),可这样:RewriteEngine On RewriteRule ^/legacy/ - [R=410,L] ErrorDocument 410 /errors/legacy-retired.html
? 动态错误页增强实用性(推荐)
把 ErrorDocument 指向 .php 文件,就能记录日志、适配设备、甚至尝试智能跳转:
- 记录原始请求:
error_log("404 → ".$_SERVER['REQUEST_URI'], 3, "/var/log/apache/404.log"); - 区分用户和爬虫:检查
$_SERVER['HTTP_USER_AGENT'],对爬虫返回纯文本,对人返回带搜索框的 HTML - 尝试补全路径:
basename($_SERVER['REQUEST_URI'])做模糊匹配,再header("Location: ...")(注意避免循环)
⚠️ 特别注意 Proxy 场景下的行为
如果你用了 ProxyPass:
- 后端返回的
404或500默认不会触发ErrorDocument(它是后端发的,Apache 只是透传) - 要接管,必须开启
ProxyErrorOverride On,并显式配ErrorDocument 404 /...和ErrorDocument 500 /... - 同时加
ProxyPass /errors/ !,防止错误页路径又被代理走
例如:
ProxyPass / http://backend:3000/ ProxyPass /errors/ ! ProxyErrorOverride On ErrorDocument 404 /errors/404.html ErrorDocument 500 /errors/500.html
不复杂但容易忽略。









