先看状态码与页面内容是否指向同一件事:如果服务器对不存在的资源返回 200,而页面正文写着“未找到”,这就是不一致。核对时不要只刷新浏览器,而要用原始响应和渲染后内容分别取证,再决定是改状态码逻辑,还是改错误页模板。
错误页误返回成功响应,通常有三个不同来源,处理方式完全不同。
区分方法很直接:对同一批不存在的 URL,分别记录 HTTP 状态码、响应正文中的标题和关键句、以及渲染后 DOM 里是否出现错误提示。如果状态码是 200,但正文明确写“页面不存在”,问题多半在模板或中间层;如果状态码和正文都像正常页,问题在路由兜底策略。
拿你手里一个已知正常的页面和一个已知不存在的路径做对照,而不是只看错误页本身。假设站点有 /products/a 正常返回 200,再请求 /products/does-not-exist。记录四项:状态码、Content-Type、正文首个 <h1> 文本、渲染后是否出现“未找到”类提示。
如果不存在路径返回 200,且 <h1> 与正常页相同,说明兜底路由把错误请求交给了正常模板。如果返回 200,但 <h1> 是“页面不存在”,说明错误模板生效了,只是状态码没有同步设置。这个动作的结果决定下一步:前者要改路由匹配和兜底逻辑,后者只需在错误处理分支里显式设置状态码。
常见取舍是:在应用层统一修正状态码,还是在反向代理层拦截并改写。两者都成立,但条件不同。
判断依据是错误页的生成位置。如果正文里的错误提示来自应用模板,优先在应用层修;如果正文是静态 HTML,且应用只负责返回文件,代理层改写更现实。不要在两层同时改同一条规则,否则后续排查时很难判断是哪一层生效。
修复后不要只测一个 URL。至少覆盖三类:一个确实不存在的路径、一个存在但无权限的路径、一个参数错误但路径存在的请求。对每一类记录状态码和正文错误提示是否同时出现。
如果状态码变成 404,但正文仍是正常页内容,说明只改了状态码,没有改模板,抓取端仍可能把页面当作有效内容处理。如果正文是错误提示,状态码仍是 200,说明模板分支没有走到设置状态码的代码。只有两者同时指向错误,才算这一层一致。
另外要区分“抓取限制”和“索引移除”:即使错误页返回 404,也不等于它一定会从索引中消失;robots.txt 的 disallow 只限制抓取,不保证移除已收录 URL。状态码和内容一致只是让抓取端能正确判断页面性质,后续是否移除仍取决于搜索引擎各自的处理。
按下面顺序处理你手中的页面,不要跳步:
完成这五步后,你得到的不只是一个状态码,而是一组能复查的证据:请求、响应、渲染结果和修改位置。下一步无论是提交重新抓取,还是继续排查其他错误页,都以这组证据为基准,而不是凭浏览器里看到的一个页面下结论。