根据你提供的信息,我看到你遇到了一个典型的跨域资源共享(CORS)问题。当你使用 <a href> 标签时,这是一个完整的页面导航,不受同源策略限制;而使用 fetchaxios 等 AJAX 请求时,浏览器会强制执行同源策略,需要服务器明确允许跨域访问。

问题原因

  1. 同源策略限制:浏览器只允许访问同源(协议、域名、端口都相同)的资源,除非服务器通过 CORS 头明确允许。
  2. CORS 预检请求(Preflight):对于某些类型的请求(如非简单请求),浏览器会先发送一个 OPTIONS 请求进行预检,确认服务器是否允许该请求。
  3. 服务器配置问题:你的后端服务可能没有正确配置 CORS 头,导致预检请求失败。

解决方案

1. 修改后端 CORS 配置

确保后端服务正确配置 CORS 头,允许来自前端域名的请求:

// service2.js(假设这是你的后端服务)
const express = require('express');
const app = express();
const PORT = 4001;

// 允许特定前端域名(如 http://10.20.93.252:4000)
app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', 'http://10.20.93.252:4000');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With');
  res.setHeader('Access-Control-Allow-Credentials', 'true'); // 如果需要传递凭证(如cookies)
  
  // 处理预检请求
  if (req.method === 'OPTIONS') {
    return res.sendStatus(200);
  }
  
  next();
});

// API路由
app.get('/api/gitlab/merge_requestses', (req, res) => {
  // 处理请求逻辑
  res.json({ message: '成功获取MR数据' });
});

app.listen(PORT, () => {
  console.log(`服务运行在 http://localhost:${PORT}`);
});
2. 使用代理服务器(开发环境)

如果你在开发环境中,可以配置一个代理服务器来转发请求,避免跨域问题:

// 在前端项目中配置代理(如使用create-react-app)
// package.json 中添加:
{
  "proxy": "http://10.20.93.252:4001"
}

// 然后在前端代码中使用相对路径:
fetch('/api/gitlab/merge_requestses')
  .then(response => response.json())
  .catch(error => console.error('请求失败:', error));
3. 检查前端请求配置

确保你的 fetchaxios 请求没有额外的配置导致预检请求失败:

// 使用fetch的正确方式
fetch('http://10.20.93.252:4001/api/gitlab/merge_requestses', {
  method: 'GET',
  headers: {
    // 避免添加不必要的头,可能触发预检请求
    // 'Content-Type': 'application/json' // 对于GET请求不需要这个头
  }
})
  .then(response => response.json())
  .catch(error => console.error('请求失败:', error));

// 使用axios的正确方式
axios.get('http://10.20.93.252:4001/api/gitlab/merge_requestses')
  .then(response => console.log(response.data))
  .catch(error => console.error('请求失败:', error));
4. 使用 JSONP(仅适用于 GET 请求)

如果上述方法都无法解决,可以考虑使用 JSONP(JSON with Padding),但它只支持 GET 请求:

function handleResponse(data) {
  console.log('获取的数据:', data);
}

const script = document.createElement('script');
script.src = 'http://10.20.93.252:4001/api/gitlab/merge_requestses?callback=handleResponse';
document.body.appendChild(script);

调试建议

  1. 查看浏览器开发者工具

    • 在 Network 面板中查看请求和响应头
    • 检查是否有 CORS 相关的错误信息
    • 查看 OPTIONS 请求的响应状态和头
  2. 使用 Postman 测试 API

    • 确认 API 本身是否正常工作
    • 检查响应头是否包含正确的 CORS 信息
  3. 临时允许所有域名(仅用于测试)

    • 在开发环境中,可以临时将 Access-Control-Allow-Origin 设置为 *,但注意生产环境不要这样做:
      res.setHeader('Access-Control-Allow-Origin', '*');
      

通过以上方法,通过上面的第二段,加一句这个就好了,可以用API的fetch与anxos接口访问了,而不用href去测试了,一直还以为是NGINX代理或者防火墙问题呢.
// package.json 中添加:
{
“proxy”: “http://10.20.93.252:4001”
}

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐