页面能打开,列表却一直转圈;用接口工具请求正常,浏览器却报Network Error。遇到这种情况,先不要给所有接口加跨域头。“请求失败”可能发生在发送之前、网络连接中,也可能是响应回来后被浏览器限制读取。
排查顺序是:完整请求地址、浏览器错误、预检请求、真实业务响应,最后才是前端如何解析结果。本文以Vue、Nginx与Spring Boot为例,说明这几层如何区分。
一、先找到请求发到哪里
在Network中查看完整URL。若线上页面请求http://localhost:8080,它找的是访问者的电脑。开发环境的代理配置通常不会被编译成生产服务器代理,上传dist不会自动把开发代理一起带走。

图1:沿实际请求URL检查前端配置、浏览器限制、网络代理和接口响应,先确认请求停在哪一层。
把协议、域名、端口、路径分别记录。https://app.example.com/api/projects与https://api.example.com/projects不仅路径不同,还涉及跨源访问。Vite客户端环境变量通常在构建时替换,修改服务器上的同名环境变量不一定能改变已经生成的JS。
二、不同错误对应不同检查
| ERR_NAME_NOT_RESOLVED | DNS | 检查域名解析 |
| ERR_CONNECTION_REFUSED | TCP连接 | 核对监听与入口 |
| Mixed Content | 浏览器安全限制 | 统一HTTPS路径 |
| CORS错误 | 跨源响应读取 | 查看OPTIONS与响应头 |
| 已有4xx或5xx | 网关或应用 | 查真实状态与响应 |
| 200但解析失败 | 响应内容 | 检查HTML、JSON和类型 |

图2:连接失败、响应不可读和响应内容异常是不同问题,前端报错也不代表后台一定没有执行。
前端状态0或Network Error不是一个服务端HTTP状态码。它不足以说明后台根本没处理请求。有些跨域请求已经执行,只是返回结果不能被页面读取,所以涉及新增、付款等动作时不要盲目重复提交。
三、为什么接口工具能用,浏览器不能用
CORS是浏览器实施的跨源读取机制。命令行工具通常不执行同源策略,因此curl成功不能证明网页跨域配置正确。
携带Authorization或使用非简单请求头的方法,可能先发送OPTIONS预检。下面只验证预检响应,不执行真实POST业务:
curl -i -X OPTIONS https://api.example.com/projects \\
-H 'Origin: https://app.example.com' \\
-H 'Access-Control-Request-Method: POST' \\
-H 'Access-Control-Request-Headers: authorization,content-type'
检查允许来源是否与页面来源匹配、允许方法和请求头是否覆盖实际请求。预检一般不应要求已有用户会话;真正接口仍要执行认证和授权。预检通过后还应检查真实响应,包括错误响应是否具备相应CORS头。

图3:需要预检的跨域请求先发送OPTIONS,预检通过后,业务请求仍需独立完成认证和授权。
使用跨源Cookie时,需要客户端凭据选项与服务端允许凭据配合,并检查Cookie本身的属性。允许凭据的响应不能用Access-Control-Allow-Origin: *替代明确来源。动态允许来源应使用受控列表并合理设置Vary: Origin。
四、同源代理可以减少配置交叉
小型管理系统可以让前端请求相对路径/api/,由同一域名下的Nginx转发到后台。浏览器看到同源入口,后台仍可保留内网地址。
const response = await fetch('/api/projects');
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const type = response.headers.get('content-type') || '';
if (!type.includes('application/json')) {
throw new Error('Expected JSON response');
}
const data = await response.json();
这是响应检查示例,认证凭据需要接入项目已有请求层。fetch遇到404或500不会自动按网络失败拒绝Promise,因此要检查response.ok。后端业务码也要按API契约额外判断。

图4:开发代理与生产代理运行在不同位置,构建发布后仍需配置正确的API地址和转发规则。
同源设计不替代接口权限。跨域设计也并非错误:多个前端共享API时可以采用,但要明确由网关还是应用统一管理CORS。两层同时追加头,可能产生重复且无效的响应。
五、一个容易误诊的例子
假设浏览器提示CORS,后台日志却显示数据库异常。网关生成的500错误页没有CORS头,浏览器只能向前端暴露跨域失败。此时根因是后台异常,跨域错误是第二层表现。
做法是先查失败时间对应的入口日志和上游状态,恢复真实接口,再验证错误响应也能被受信任页面正确读取。只放开跨域不会修复数据库。
六、最低接口验收表

图5:地址、连接、跨域和响应逐项核对,涉及写操作时还需确认失败请求是否已经产生业务结果。
| 生产地址 | 没有意外localhost或开发端口 |
| 协议 | HTTPS页面没有被阻止的HTTP请求 |
| 预检 | 方法、来源和请求头匹配 |
| 错误处理 | 401、403、500能按契约展示 |
| 数据结果 | 只读和授权写操作都验证过 |
排查时可以保存脱敏的请求头、响应头和时间,但不要直接公开带Cookie和Token的HAR文件。先找到请求在哪一步失败,再让AI针对该步骤分析,通常比让它全面修改跨域配置更容易收敛。
参考资料
- MDN CORS机制
- Spring Security CORS集成
- Vite环境变量与模式




