使用FetchAPI调用SonarQube API无返回结果,仅返回不透明令牌
你的问题核心在于使用了mode: 'no-cors'这个配置,它直接导致了你无法读取SonarQube API的响应内容,进而触发解析JSON的错误。
为什么no-cors会搞砸一切?
当你设置mode: 'no-cors'时,浏览器会严格限制请求的响应权限——你得到的是一个不透明响应(opaque response),这种响应的内容完全无法被前端脚本读取,甚至连响应状态码、headers都拿不到。这就是为什么你调用res.json()会抛出Unexpected end of input错误:根本没有可解析的JSON内容,响应是空的或者浏览器不让你查看。
你之前遇到的CORS错误,本质是浏览器的同源策略限制,而no-cors并不是解决办法,只是“掩耳盗铃”地绕过了错误提示,但同时也封死了获取数据的路径。
正确解决思路:搞定CORS问题,而非绕过
既然Chrome地址栏和Postman能正常访问,说明API本身是没问题的,我们需要让前端脚本也能合法访问它,有几种可行方案:
1. 配置SonarQube允许跨域请求
直接在SonarQube的配置文件中添加CORS相关的响应头,允许你的前端域名访问:
- 找到SonarQube安装目录下的
conf/sonar.properties文件 - 添加以下配置(生产环境建议指定具体域名,
*表示允许所有):
sonar.web.http.headers=Access-Control-Allow-Origin: *, Access-Control-Allow-Methods: GET, POST, OPTIONS, Access-Control-Allow-Headers: Authorization, Content-Type
- 重启SonarQube服务
2. 使用反向代理(开发/生产环境都适用)
如果无法修改SonarQube的配置,你可以通过代理服务器转发请求,规避同源策略:
- 开发环境:比如在React项目中,创建
src/setupProxy.js文件:
const { createProxyMiddleware } = require('http-proxy-middleware'); module.exports = function(app) { app.use( '/api', createProxyMiddleware({ target: 'http://localhost:9000', changeOrigin: true, }) ); };
然后前端请求改为fetch("/api/issues/search?pageSize=500&componentKeys=bactch_analysis_key"),请求会被代理到SonarQube,不会有CORS问题。
- 生产环境:可以用Nginx做反向代理,配置示例:
server { listen 80; server_name your-frontend-domain.com; location /api/ { proxy_pass http://localhost:9000/api/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }
3. 别忘了SonarQube的认证
SonarQube API大多需要认证才能访问,你需要在fetch请求中添加Authorization头。如果用的是SonarQube的令牌,格式是把令牌作为用户名,密码留空:
const sonarToken = 'your-sonar-token-here'; fetch("http://localhost:9000/api/issues/search?pageSize=500&componentKeys=bactch_analysis_key", { headers: { 'Authorization': 'Basic ' + btoa(`${sonarToken}:`) } }) .then(res => res.json()) .then(data => { console.log(data); }) .catch(err => { console.log(err); });
为什么Chrome地址栏和Postman能访问?
- 浏览器地址栏发起的请求不属于“脚本发起的跨域请求”,不受同源策略限制;
- Postman是独立的客户端工具,根本不遵循浏览器的同源策略规则,所以可以直接访问任何API。
内容的提问来源于stack exchange,提问作者Aakash Thakur

