Apache中实现404错误页需用RewriteCond判断文件/目录不存在,再通过RewriteRule内部重写至/404.html并加[R=404,L]确保返回正确状态码、不跳转、不改地址栏,兼顾SEO与用户体验。

Apache 中错误页面重写,核心目标是:让不存在的请求(404)被统一交给自定义页面处理,同时保持 HTTP 状态码为 404(对 SEO 友好),且不跳转、不改变地址栏。这和普通重定向不同——它不是把用户“拉走”,而是让服务器悄悄用你的 404 页面响应那个错误请求。
✅ 正确做法:用 ErrorDocument + RewriteCond 组合实现可控 404
单纯靠 ErrorDocument 404 /404.html 是最简方式,但它只在 Apache 真正找不到文件时触发,不经过 .htaccess 重写流程,也无法做条件判断(比如只对某类 URL 生效)。
更灵活、更常用的做法是:先拦截所有未命中文件/目录的请求,再内部重写到你的 404 页面,并显式返回 404 状态码。
1. 基础兜底式 404 重写(推荐)
适用于大多数 PHP 项目(如自建站点、Laravel、WordPress 等):
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /404.html [R=404,L]-
!-f:请求路径不是真实存在的文件 -
!-d:请求路径不是真实存在的目录 -
[R=404,L]:返回 HTTP 404 状态码(不是跳转!),并停止后续规则 -
/404.html必须放在网站根目录,且能被 Apache 直接读取
⚠️ 注意:不要写成
[R=302,L]或[R,L],那会变成 302 跳转,搜索引擎会认为页面临时移动,影响 SEO。
Apache Superset Dashboard and SQL Exploration Skill下载Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
2. 配合 ErrorDocument 的双重保险写法
有些环境(如共享主机)可能限制 R=404,这时可退而求其次,用 ErrorDocument 主控 + .htaccess 辅助:
ErrorDocument 404 /404.html
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /404.html [L]
</IfModule>-
ErrorDocument是 Apache 底层兜底,确保即使重写失效也能显示 404 页面 -
<IfModule>防止模块未启用时报错 - 这里
[L]表示内部重写,浏览器地址栏不变,状态码仍由ErrorDocument控制为 404
3. 按路径条件触发 404(进阶控制)
比如只想对 /api/ 下的不存在接口返回 JSON 格式 404:
RewriteCond %{REQUEST_URI} ^/api/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /api-404.php [R=404,L]-
/api-404.php可输出header('HTTP/1.1 404 Not Found');和 JSON 内容 - 精准匹配,不影响其他路径
❌ 常见错误写法(会导致全站 404 或循环)
-
RewriteRule ^(.*)$ /404.html(没加RewriteCond)→ 所有请求都进 404,包括index.php、style.css -
RewriteRule ^404\.html$ - [F]→ 把 404 页面自己封掉,反而打不开 -
RewriteRule ^(.*)$ /404.html [R,L]→ 返回 302,地址栏变https://site.com/404.html,SEO 不友好 -
RewriteRule ^(.*)$ /404.html [L]→ 状态码仍是 200,搜索引擎当正常页面收录
? 验证是否生效
- 访问一个确定不存在的路径(如
/xyz123abc) - 查看浏览器开发者工具 Network 标签页:
- Status 应为
404 Not Found(不是 200 或 302) - Response Headers 中应有
Content-Type: text/html(或你页面的实际类型) - 地址栏 URL 保持不变(说明是内部响应,不是跳转)
- Status 应为
- 检查 Apache 错误日志,确认无
rewrite相关报错(如bad flag delimiters)
不复杂但容易忽略


















