软件研发 --- 为什么我开发环境的接口工作不正常与测试结果不一样,为什么一个请求发了两次
通过服务器抓包分析后发现在开发环境一个post被发送了两次,导致在第一个错误的post中等待响应,而服务器返回了第二个post内容,会有一种错乱的感觉。而部署代码后没有这个问题。
问题原因:
在 Vue 开发中,使用代理转发解决 CORS 问题时出现 一个 TCP 流中包含两次相同请求 的现象,通常是由以下原因造成的:
1. 浏览器预检请求 (Preflight Request)
这是最常见的原因。当你的请求触发 CORS 预检机制 时,浏览器会先发送一个 OPTIONS
请求,验证通过后再发送真正的请求(如 GET/POST
)。两次请求共享同一个 TCP 连接,因此在网络抓包工具(如 Wireshark)中会看到同一个 TCP 流中有两次请求。
触发条件:
-
请求包含自定义 Header(如
Authorization
、X-Token
)。 -
使用
Content-Type: application/json
(非简单内容类型)。 -
请求方法为
PUT
、DELETE
等非简单方法。
解决方案:
-
后端配置 CORS 响应头:确保服务器正确响应
OPTIONS
请求,返回以下 Header:Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS Access-Control-Allow-Headers: Authorization, Content-Type, ...
-
代理层统一处理 OPTIONS:在代理服务器(如 Nginx)中添加预检请求的响应配置。
2. 代理配置重复转发
若代理配置错误(如路径匹配重叠),可能导致请求被转发两次。
示例错误配置(Vue CLI 的 vue.config.js
):
// ❌ 错误:两个规则同时匹配同一路径
module.exports = {
devServer: {
proxy: {
'/api': { target: 'http://backend.com' },
'/api/v1': { target: 'http://another-backend.com' } // 重复匹配
}
}
}
解决方案:
-
检查代理路径规则:确保规则无重叠,更精确的路径应放在前面:
// ✅ 正确:精确路径优先 proxy: { '/api/v1': { target: 'http://backend.com' }, // 精确匹配 '/api': { target: 'http://backend.com' } // 泛匹配 }
3. 前端代码重复调用
前端逻辑错误(如事件重复绑定)可能导致连续发送两次相同请求。
常见场景:
-
按钮点击事件被多次绑定(如
@click
重复注册)。 -
Vue 生命周期钩子(如
created
)中重复调用方法。 -
未取消的异步操作(如连续触发
setTimeout
)。
解决方案:
-
检查事件监听器,避免重复绑定。
-
使用防抖(
debounce
)或取消标记(AbortController)控制请求。
4. HTTP 长连接复用 (Keep-Alive)
浏览器默认复用 TCP 连接(Connection: keep-alive
),多个请求可能复用同一个 TCP 流。这是正常行为,无需处理。
排查步骤:
-
查看请求类型:
在浏览器开发者工具的 Network 面板中,确认两次请求分别是:-
第一次:
OPTIONS
(预检请求) -
第二次:真实请求(如
GET/POST
)
-
-
检查代理配置:
确保代理路径无冲突,且未重复转发。 -
简化请求:
临时移除自定义 Header 和Content-Type: application/json
,观察是否仍出现两次请求。 -
抓包分析:
使用 Wireshark 或 Fiddler 检查 TCP 流中的具体请求内容,确认是否为预检请求。
总结建议:
现象 | 原因 | 解决方案 |
---|---|---|
一次 OPTIONS + 一次真实请求 |
CORS 预检机制 | 后端配置正确的 CORS 响应头 |
两次相同真实请求 | 代理配置冲突或前端代码问题 | 检查代理路径规则及前端逻辑 |
同一 TCP 流中多个请求 | HTTP Keep-Alive 复用连接 | 正常现象,无需处理 |
通过以上方法定位问题后,针对性地调整代理配置、后端 CORS 设置或前端代码即可解决。