🔥 前端请求返回 HTTP Status 0?这个坑 90% 的开发者都会踩!
🔥 前端请求返回 HTTP Status 0?这个坑 90% 的开发者都会踩!

服务器明明好好的,前端却报错:status 0?问题可能就藏在你忽略的那一行配置里。
💡 问题现象
最近在项目开发中遇到了一个诡异的问题:
- ✅ 后端 API 完全正常
- ✅ CORS 配置正确无误
- ✅ Cookie 中有有效 token
- ✅ 手动测试都能成功
- ❌ 但前端页面请求就是返回 HTTP Status 0
// 前端控制台报错
API 响应不是有效的 JSON: http://localhost:9421/api/v1/media?page=1&per_page=20, status: 0
🐛 排查过程
第一步:验证后端
直接在浏览器访问 API,成功返回数据!说明后端没问题。
curl http://localhost:9421/api/v1/media/?page=1&per_page=20
# ✅ 返回正常 JSON 数据
第二步:检查 CORS
测试 OPTIONS 预检请求,完美通过!
// CORS 头都正确
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Credentials: true
第三步:验证认证
Cookie 中有有效的 JWT token,手动发起请求测试:
// ✅ 成功
fetch('http://localhost:9421/api/v1/media/?page=1&per_page=20', {
credentials: 'include',
headers: {
'Authorization': 'Bearer xxx'
}
})
// Status: 200 ✓
第四步:排除插件干扰
为了彻底排除浏览器插件(如广告拦截器、代理扩展等)对请求的干扰,我们在无痕模式下禁用了所有插件和脚本,再次发起请求。
// 在无痕模式下,所有扩展默认禁用
fetch('http://localhost:9421/api/v1/media/?page=1&per_page=20', {
credentials: 'include'
})
// 结果:仍然返回 status 0
确认问题与插件无关,继续深入调试。
第五步:发现问题
继续深入调试,发现了一个关键信息:
Response {
status: 0,
type: "opaqueredirect", // ← 关键!
ok: false,
headers: {} // 空的!
}
opaque-redirect 是什么鬼?!
🎯 问题根源
原来,问题出在这行代码上:
// ❌ 错误的配置
const response = await fetch(url, {
method: 'GET',
credentials: 'include',
redirect: 'manual' // ← 就是这个!
});
什么是 redirect: 'manual'?
Fetch API 提供了三种重定向模式:
| 模式 | 行为 | 使用场景 |
|---|---|---|
follow(默认) |
自动跟随重定向 | 大多数情况 |
manual |
不跟随重定向,返回 opaque-redirect | 需要手动处理重定向 URL |
error |
遇到重定向直接报错 | 严格模式 |
为什么会返回 Status 0?
- 前端请求发送后,后端返回 3xx 重定向响应(比如重定向到登录页)
- 因为设置了
redirect: 'manual',浏览器不会跟随重定向 - 浏览器返回一个 opaque-redirect 类型的响应
- 这个响应的
status = 0,headers = {},body 为空 - 尝试解析 JSON 时就会报错:"Unexpected end of input"
为什么会有 redirect: 'manual' 这个选项?
既然这个选项这么容易出问题,那它存在的意义是什么?
根据 Fetch 规范,redirect: 'manual' 的设计初衷主要是为了浏览器内部导航和Service Worker 等特定场景。在这些场景下,开发者需要完全控制重定向的处理流程。但对于普通的前端应用代码,你几乎永远不需要用到它。
换句话说:除非你在写 Service Worker 或做非常底层的网络控制,否则永远不要碰 redirect: 'manual'!
✅ 解决方案
方案 1:移除 redirect: 'manual'(推荐)
// ✅ 正确的做法
const response = await fetch(url, {
method: 'GET',
credentials: 'include'
// 不设置 redirect,使用默认的 'follow'
});
让浏览器自动处理重定向,99% 的情况都应该这样做!
方案 2:如果你确实需要处理重定向(但不用 manual)
// 正确的重定向处理方式:在响应中判断状态码
const response = await fetch(url, {
method: 'GET',
credentials: 'include'
});
if (response.redirected) {
// 重定向发生了,response.url 已经是最终 URL
console.log('重定向到了:', response.url);
}
if (response.status === 302) {
// 也可以手动获取重定向地址(但不推荐手动跳转)
const location = response.headers.get('Location');
}
注意:使用默认的 follow 模式,浏览器会自动跟随重定向,你拿到的是最终响应。response.redirected 属性可以告诉你是否发生过重定向。
📝 最佳实践
✅ DO(推荐做法)
// 1. 使用默认配置
fetch('/api/data', {
method: 'GET',
credentials: 'include'
});
// 2. 如果需要处理认证失败,在响应中判断
fetch('/api/data', {
credentials: 'include'
})
.then(response => {
if (response.status === 401) {
// 未认证,跳转到登录页
window.location.href = '/login';
}
return response.json();
});
// 3. 检查是否发生了重定向
const response = await fetch('/api/data');
if (response.redirected) {
console.log('请求被重定向到了:', response.url);
}
❌ DON'T(避免这样做)
// 1. 不要随意设置 redirect: 'manual'
fetch('/api/data', {
redirect: 'manual' // ❌ 除非你非常清楚后果
});
// 2. 不要这样手动处理重定向(这是错误的示范)
fetch('/api/data', {
redirect: 'manual'
}).then(response => {
// 这段代码几乎永远不会按预期工作!
if (response.type === 'opaqueredirect') {
window.location.href = response.headers.get('Location'); // headers 是空的!
}
});
🔍 扩展:还有哪些情况会导致 Status 0?
除了 redirect: 'manual' 导致的 opaque-redirect 外,status 0 还可能由以下原因引起:
| 原因 | 说明 |
|---|---|
| 网络连接问题 | 网络断开、WiFi 信号差、飞行模式等 |
| 跨域请求被阻止 | CORS 配置不当,OPTIONS 预检失败 |
| 请求被取消 | 页面刷新、导航导致请求被中断 |
| 协议混合问题 | HTTPS 页面请求 HTTP 资源被浏览器阻止 |
| DNS 解析失败 | 域名无法解析 |
所以,当你遇到 status 0 时,可以先按以下步骤快速排查:
- 打开浏览器开发者工具 → Network 面板
- 查看请求是否真的发出了?状态列显示什么?
- 如果有请求但状态为
(failed)或(canceled),检查网络和 CORS - 如果请求显示为
302但代码里报 status 0,极大概率就是本文的问题
💡 一个真实案例
有开发者在微信公众号 H5 开发中遇到过类似问题:iOS 10 系统下,设置了自定义 header 后,所有请求都返回 status 0。排查发现是自定义 header 触发了 CORS 预检,而 iOS 10 对 CORS 预检的兼容性有问题,后端返回的 Access-Control-Allow-Headers: * 不被识别,导致真正的请求没有被发送。
解决方法是将 * 改为明确列出的 header 名称:
Access-Control-Allow-Headers: content-type, auth
这个案例告诉我们:status 0 是浏览器层面的“请求没发出去”或“响应被拦截”,通常不是后端业务错误,要从前端/网络层面找原因。
🎓 学到的教训
- 不要过度设计 - 浏览器的默认行为通常是最好的
- 理解 HTTP 状态码 - Status 0 不代表服务器错误,而是网络层面的问题
- 善用调试工具 - Network 面板能看到请求的详细信息
- 了解 Fetch API - 各种参数的含义和使用场景,特别是
redirect这个容易被忽视的选项 - 遇到 status 0,先检查网络和配置,再怀疑后端 - 因为请求根本没到服务器
🔗 相关资源
💬 互动话题
你在开发中遇到过哪些诡异的 HTTP 错误?欢迎在评论区分享你的故事!
👍 如果这篇文章帮到了你,请点赞、在看、转发三连!
希望这篇推文能帮助更多开发者避开这个坑!🚀
本文来自博客园,作者:Athenavi,转载请注明原文链接:https://www.cnblogs.com/Athenavi/p/19808133

浙公网安备 33010602011771号