404 是什么
404 Not Found 表示服务器找不到与请求 URI 匹配的资源:URL 写错、路由未注册、资源已被删除,或出于安全考虑刻意隐藏,都会返回这个码。它属于 4xx 客户端错误类,语义是「服务器理解请求但找不到目标」,而不是「服务器处理失败」。RFC 9110 §15.5.5 允许用 404 掩盖 403 的存在性,避免攻击者通过状态码差异探测哪些路径真实存在。若资源是被永久删除且愿意公开这一事实,410 Gone 的语义更准确,搜索引擎也会更快摘除索引。
基本信息
| 状态码 | 404 Not Found(RFC 9110 §15.5.5) |
|---|---|
| 所属类别 | 4xx 客户端错误类 |
| 谁在返回 | 网关与 Web 服务器、应用框架路由、对象存储、CDN 回源 |
| 可否缓存 | 允许缓存但默认不缓存;一旦被缓存会持续返回旧结果 |
| 与 410 区别 | 410 表示资源已永久删除;404 只表示当前找不到 |
典型使用场景
- 访问不存在的页面或接口,由服务端给出自定义错误页
- SPA 前端路由:刷新子路由时需服务端回退到首页文件,否则刷新即 404
- 接口下线:路径停用后保留 404 而不做跳转,让调用方及时发现
- 监控与探测:健康检查把 404 视为路径不存在,而非服务不可用
- 安全隐藏:把内部或未授权路径返回 404,隐藏资源是否存在
验证 404 与路由
验证 404 与路由
curl -si https://api.example.com/items/does-not-exist | head -5 # 看 Server 与错误体风格,判断 404 由谁返回
curl -s https://api.example.com/openapi.json | jq -r '.paths | keys[]' # 用接口清单核对路由是否注册
curl -si http://10.0.0.5/ -H 'Host: www.example.com' # 直连源站指定 Host,绕开 CDN 验证源站
nginx -T | grep -nE 'root|try_files|location' # 检查站点根目录与回退规则
ls -l /var/www/site/index.html # 确认静态文件存在且运行用户可读不同来源的 404 怎么认
| 返回者 | 典型特征 | 排查入口 |
|---|---|---|
| 网关与 Web 服务器 | 默认错误页,无应用特征头 | 站点根目录、location、回退规则 |
| 应用框架 | 自带 JSON 错误体与请求编号 | 框架路由表、日志中的请求路径 |
| 对象存储 | 返回 XML 格式的键不存在错误 | 存储桶权限、对象键名大小写与斜杠 |
| CDN | 命中缓存时无回源日志 | 刷新缓存后重试,再看回源日志 |
Nginx 错误页与回退
Nginx 错误页与回退
server {
error_page 404 /404.html;
location = /404.html { internal; } # 只能内部跳转,避免被直接访问
location / { try_files $uri $uri/ /index.html; } # 单页应用回退示例
}单页应用部署后刷新子路由 404 是最高频的问题:Nginx 需要把未命中的路径交给首页处理,否则只有首页能打开,用户刷新任何子路由都报错。
CDN 按长 TTL 缓存了 404 响应,会造成资源上线后仍持续报错;应给错误响应设短缓存并在发布后主动刷新对应地址。
排障顺序
- 先确认 404 由谁返回:看响应头的服务器字段与错误体风格,网关与应用框架的错误页差别明显
- 再核对请求路径有没有被网关改写:带前缀的转发规则可能把路径截断或多加一段
- 检查源站文件与权限:静态站点文件不存在,或运行用户读不到,都会呈现为 404
- 对比 CDN 与源站:直连源站正常而经 CDN 报错,问题就落在缓存或回源配置上
- 最后看路由表与接口清单:应用侧路由未注册时,源站自身就会返回 404
同类状态码怎么选
| 场景 | 更合适的码 | 理由 |
|---|---|---|
| 路径从未存在过 | 404 | 最通用,客户端与爬虫都按资源不存在处理 |
| 资源被永久删除且愿意公开 | 410 | 搜索引擎会更快摘除索引,语义也更明确 |
| 资源存在但无权限 | 403 或伪装成 404 | 对外隐藏存在性用 404,对内排障用 403 更清楚 |
| 站点整体迁移 | 301 | 配合新地址做跳转,而不是逐条返回找不到 |