前端知库

前端网络问题应该怎样按协议层排查?

通过请求失败、旧内容和流式响应三个场景,按 URL/DNS、连接/TLS、HTTP、浏览器策略和应用数据层收集证据,避免把所有问题都归为 CORS 或后端异常。

参考答案

简答

  • “请求失败”可能出在 DNS、TLS、HTTP 状态、CORS、缓存或 Service Worker 等不同层。
  • 先确认最终 URL、源和重定向链;DNS、连接、TLS 错误不能靠改 CORS 修复。
  • HTTP 状态、响应类型和业务结果要分开检查;CORS 要分别看预检和实际请求。
  • 缓存和 Service Worker 会改变响应来源,流式响应还要检查缓冲与分帧。

前端看到“请求失败”时,可能是 DNS 没找到地址、TLS 证书被拒绝、服务器返回 503、浏览器阻止了 CORS、Service Worker 返回旧响应,也可能是接口返回 200 但 JSON 结构错误。每一层的证据和修复方式都不同。

排查的第一原则是先保存原始事实:完整 URL、请求方法、状态、响应头、请求头、时间线、控制台错误和响应体摘要。不要先改代码、清缓存或把所有域名都加入白名单。

先确认请求身份和部署位置

检查协议、主机、端口、路径、查询参数和重定向链。相对 URL 会受到当前页面 base、子目录部署和 <base> 标签影响;同一段 fetch 在开发服务器和生产子路径中可能请求不同地址。

如果请求根本没有出现在 Network 中,可能是代码分支、Service Worker、预加载或浏览器策略在更早阶段阻止了它。若出现了请求,要区分它是预检、实际请求、重试还是另一个相似路径的请求。

DNS、连接和 TLS 错误不能靠 CORS 修复

域名解析失败、连接超时、证书域名不匹配或 TLS 版本问题,通常在 HTTP 响应之前发生。浏览器脚本可能只得到一个笼统的网络错误,开发者工具、系统 DNS 工具、代理日志和证书检查才能提供更多证据。

bash
curl -I -L --max-time 15 https://api.example.com/health

命令行成功不证明浏览器可以读取响应,因为 curl 不实施同源策略、Cookie 分区和 Permissions Policy;命令行失败也要确认它使用的 DNS、代理和证书环境是否与浏览器相同。TLS 调试时不要关闭证书验证来“确认接口能不能用”,那会掩盖真正的身份和链路问题。

HTTP 状态、响应类型和业务结果分开看

拿到 200 只证明 HTTP 层返回成功。还要检查 Content-Type、Content-Encoding、Content-Length、缓存头、响应体和业务字段。登录过期可能返回 HTML 登录页,接口请求随后在 JSON.parse 阶段失败;这不是 JSON 库随机坏了。

404、401、403、409、429、502 和 504 需要不同恢复策略。写操作在超时后可能已经执行,不能只看到 504 就自动重试;429 和 503 还要查看 Retry-After。缓存的旧错误页也可能让当前源站已经修复但用户仍看到失败。

CORS 要按预检和实际响应两个请求检查

对于 JSON、PUT 或自定义请求头,先看 OPTIONS 是否发送、响应是否允许真实方法和请求头;再看实际请求是否发送、是否带 Cookie,以及实际响应是否有匹配的 Access-Control-Allow-Origin 和凭据配置。

预检成功不代表实际响应可读。实际响应缺少 CORS 头时,服务器可能已经执行了操作,浏览器只是阻止脚本读取结果。反过来,预检失败时实际请求通常不会发送。这个区别决定了是否需要检查重复写入和 CSRF,而不是只在前端换一个 mode。

Access-Control-Allow-Origin 不能写成带路径的 URL;凭据请求不能使用 *;需要读取自定义响应头时还要检查 Access-Control-Expose-Headers。服务端动态回显 Origin 还要有白名单和适当的 Vary,不能把任意来源当成可信。

缓存和 Service Worker 会改变你看到的来源

检查 Age、ETag、Cache-Control、Vary 和平台命中头,确认响应来自浏览器、CDN 还是源站。页面更新后看到旧 HTML,可能导致旧哈希资源、错误的 API base 或旧数据继续使用;清浏览器缓存只是诊断手段,不是发布策略。

Service Worker 可能在 Network 面板之前拦截请求。要排查它,查看当前控制器、Cache Storage、更新状态和缓存命中;暂时在测试环境禁用 Service Worker 可以定位问题,但不能把禁用后的网络结果当成离线功能验证。

流式响应要检查缓冲和分帧

SSE、fetch 流和 WebSocket 问题不能只看请求是否 200。要检查媒体类型、事件分隔符、代理缓冲、压缩、连接空闲超时和客户端消费速度。服务端日志写出一小块,不代表浏览器已经收到并派发了事件;CDN 或反向代理可能攒够数据后才转发。

流式协议的消息边界也要按协议处理。一次 read 不一定是一行、一条 JSON 或一条 WebSocket 业务消息。解析器要保留跨块残片,遇到半条消息、重复事件和断线重连时记录游标与恢复行为。

使用证据形成最短排查路径

可以按这个顺序记录:

  1. 页面实际 origin、请求 URL 和最终重定向;
  2. DNS/连接/TLS 是否完成;
  3. 是否有 Service Worker、预检或重试;
  4. 实际状态码、响应头和响应体类型;
  5. Cookie、CORS、CSP、Permissions Policy 是否改变浏览器可见性;
  6. 解析、Schema 校验和业务状态是否成功;
  7. 缓存、代理和 CDN 是否提供了旧或错误版本。

不同工具回答不同问题:Network 展示浏览器看到的请求,Application 面板展示 Service Worker 和存储,Performance 展示主线程与流消费,服务器/CDN 日志展示回源事实,curl 或 openssl 可以帮助隔离浏览器策略。把这些证据对应起来,才不会用“前端报 CORS”掩盖证书、缓存、权限或接口契约问题。