Apache自定义404页面需用ErrorDocument 404 /404.html(路径以/开头、相对于DocumentRoot),否则易出错;静态HTML返回200状态码,须改用PHP脚本并调用http_response_code(404)确保状态正确。

Apache里怎么指定自定义404页面
直接在虚拟主机或目录配置里加 ErrorDocument 404 /404.html 就行,路径是相对于网站根目录(DocumentRoot)的,不是文件系统绝对路径。比如 DocumentRoot /var/www/html,那 /404.html 就对应 /var/www/html/404.html。
常见错误是写成绝对路径如 /var/www/html/404.html,Apache会当成 URL 路径去重定向,导致跳转失败或循环;也有人漏掉开头的 /,写成 404.html,这时 Apache 会尝试内部重写,但多数情况下返回默认 404。
- 确保
404.html文件真实存在且 Web 服务器有读取权限(尤其 SELinux 启用时可能拦截) - 路径必须以
/开头,否则被当作相对 URI 处理,行为不可靠 - 如果用的是
.htaccess,需确认AllowOverride包含FileInfo,否则ErrorDocument不生效
为什么自定义404页面返回了200状态码
这是最常被忽略的问题:Apache 默认把自定义错误页当普通响应返回,状态码仍是 200,搜索引擎和前端逻辑都以为请求成功了。根本原因是没显式设置响应状态。
解决方法只有两个——要么用 ErrorDocument 指向一个能发正确状态码的脚本,要么在 HTML 页里加服务器端逻辑。静态 HTML 本身做不到改状态码,所以纯 /404.html 必然返回 200。
- 推荐方案:用 PHP 脚本代替 HTML,开头加
http_response_code(404) - 次选方案:用
ErrorDocument 404 /404.php,里面输出 HTML 同时控制状态 - 注意:Nginx 没这个问题,它默认保持原错误状态码;Apache 的这个行为是设计如此,不是 bug
Apache 2.4 和旧版本在 ErrorDocument 上的差异
主要差别在路径解析和协议支持。2.4+ 支持用 https:// 或完整 URL 作为 ErrorDocument 目标,但会触发外部重定向(302),这会暴露你的真实路径结构,还可能让前端 JS 拿不到原始 404 状态。
更隐蔽的坑是:2.4 默认启用 mod_alias 的路径匹配逻辑,如果你同时用了 Alias 或 Redirect,ErrorDocument 可能被绕过——Apache 会先匹配别名规则,发现不匹配才 fallback 到错误页。
- 避免用外部 URL 做 404 页面,除非明确需要跳转(比如统一到 CDN 错误页)
- 检查
mod_alias和mod_rewrite规则是否意外拦截了 404 请求路径 - 2.2 和 2.4 对
AllowOverride的默认值不同,升级后若.htaccess失效,先查这个
静态资源 404 不走自定义页?检查 MIME 类型和多后缀
用户访问 /logo.png 404 了,却看到 Apache 默认页,而不是你的 /404.html,大概率是因为 Apache 认为这是“二进制资源”,跳过了内容协商流程。特别是当文件扩展名没被 AddType 正确识别,或者用了多后缀如 .js.gz 时,ErrorDocument 可能不触发。
本质是 Apache 的错误处理发生在内容类型判定之后。如果它连该用什么处理器都不知道,就直接回退到默认错误页。
- 确保所有常用静态后缀都被
AddType或AddHandler显式声明,比如AddType image/png .png - 避免在生产环境用未注册的扩展名提供资源,否则 404 无法被捕获
- 调试时用
curl -I看真实响应头,确认是否真返回了 404 状态,还是被 rewrite 成了 200
状态码是否正确、路径是否被中间规则劫持、资源类型是否被识别——这三个点卡住任何一个,自定义 404 就形同虚设。

















