React-router-redux与redux-saga的CORS请求异常排查求助
看起来你的问题核心在于前端错误添加了后端专属的CORS响应头,再加上后端可能没正确处理OPTIONS预检请求——这直接导致浏览器拦截了后续的POST登录请求,所以后端只能收到OPTIONS请求。
下面是具体的解决步骤:
1. 移除前端请求中的多余CORS头
你在请求配置的options.headers里添加了Access-Control-Allow-Origin和Access-Control-Allow-Headers,但这些是后端返回给浏览器的响应头,绝对不是前端发送请求时该携带的。浏览器看到前端发送这类头会判定请求不规范,直接拦截,导致预检失败。
修改你的Saga请求配置,删掉这两个多余的头:
const options = { body: JSON.stringify({ login, password }), method: 'POST', headers: { 'Content-Type': 'application/json', // 删掉下面这两行无效的头 // 'Access-Control-Allow-Origin': '*', // 'Access-Control-Allow-Headers': 'Origin, Content-Type, X-Requested-With, Accept' } };
2. 确保后端正确响应OPTIONS预检请求
虽然你的后端配置了允许所有Origin和方法,但必须确认后端在收到OPTIONS请求时:
- 返回
200或204状态码 - 正确返回配置的CORS响应头,包括:
Access-Control-Allow-Origin: *Access-Control-Allow-Methods: GET, PUT, POST, DELETEAccess-Control-Allow-Headers: Origin, Authorization, Content-Type, X-Requested-With, Accept, Token
浏览器发送OPTIONS预检请求是自动行为,只有后端正确响应这些头后,浏览器才会继续发送实际的POST登录请求。之前Angular 5版本能正常工作,大概率是因为旧版Angular的HTTP客户端处理预检的逻辑更宽松,或者当时后端已经正确处理了OPTIONS请求。
3. (可选)优化fetchJSON的错误处理逻辑
当前你的fetchJSON函数会在响应状态码不是200时直接reject,但OPTIONS请求的成功状态码通常是204 No Content,你可以调整逻辑让预检请求的响应被正确处理:
const fetchJSON = (url, options = {}) => new Promise((resolve, reject) => { return fetch(url, options) .then(response => { // OPTIONS请求只要状态码在200-299之间就算成功 if (options.method === 'OPTIONS' ? !response.ok : response.status !== 200) { return reject(response); } return response; }) .then(response => { // OPTIONS请求没有响应体,无需解析JSON if (options.method === 'OPTIONS') { return resolve({}); } return response.json(); }) .then(response => resolve(response)) .catch(error => reject(error)); });
不过这一步不是必须的,只要后端正确响应OPTIONS,浏览器会自动完成后续流程,不需要你在Saga里手动处理预检请求。
完成以上步骤后重新测试,应该就能看到浏览器先发送OPTIONS预检请求,后端正确响应后,再发送POST登录请求了。
内容的提问来源于stack exchange,提问作者Adrien Chapelet

