Tableau WDC跨域请求报错求助:CORS与ORB问题排查
问题详情
运行JavaScript+jQuery代码时遭遇跨域请求失败,两种场景的错误表现如下:
- 场景1(未指定
dataType):浏览器控制台报错:
Access to XMLHttpRequest at "https://apex/api" from origin "http://xyz.8888" has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
- 场景2(设置
dataType为jsonp):控制台无报错,但未收到响应,Chrome网络标签显示错误:(failed) net::ERR_BLOCKED_BY_ORB
已尝试的修改:
- 设置
dataType为jsonp - 请求头添加
Access-Control-Allow-Origin: *
相关代码:
// Download the data myConnector.getData = function(table, doneCallback) { console.log("Inside Data download"); // 到此处正常执行,Ajax请求触发错误 $.ajax({ crossDomain: true, headers: {'Access-Control-Allow-Origin': '*'}, dataType: 'jsonp', // 移除该配置触发ERROR1,保留触发ERROR2 url: 'https://apex/api', success: function(resp){ var feat = resp.features, tableData = []; // 遍历JSON对象 for (var i = 0, len = feat.length; i < len; i++) { tableData.push({ "id": feat[i].id }); } table.appendRows(tableData); doneCallback(); } }); };
解决方案
1. 纠正Access-Control-Allow-Origin的使用误区
你在请求头里添加Access-Control-Allow-Origin: *完全无效——这个是服务器返回的响应头,不是客户端请求时需要携带的。客户端发送这个头会被浏览器直接忽略,必须由目标API服务器配置,允许你的源(http://xyz.8888)或所有源(*)访问。
2. JSONP失效的原因(ERR_BLOCKED_BY_ORB)
net::ERR_BLOCKED_BY_ORB是Chrome的Origin Restricted Blob机制拦截了请求,本质是目标API不支持JSONP。JSONP要求服务器返回包裹在回调函数中的JS代码,若服务器仅返回纯JSON、或未配置JSONP所需的回调参数,就会触发该拦截。
可行解决路径
路径一:修改服务器端CORS配置
这是标准解决方案,让API服务器在响应头中添加:
Access-Control-Allow-Origin: http://xyz.8888(精准允许你的源,安全性更高),或*(允许所有源)- 若请求包含自定义头、非GET/POST方法,还需配置
Access-Control-Allow-Methods、Access-Control-Allow-Headers等,处理预检OPTIONS请求。
路径二:使用反向代理
如果无法修改服务器配置,可在前端服务(本地开发用webpack-dev-server,生产用Nginx)中配置反向代理:将前端的/api请求代理到https://apex/api,浏览器请求同域的/api,由代理服务器转发请求到目标API,避开跨域限制。
举个Nginx配置示例:
location /api { proxy_pass https://apex/api; proxy_set_header Host apex; }
前端代码中的URL改为/api即可。
路径三:确认API的跨域支持
检查目标API是否提供官方CORS支持,或是否有专门的JSONP兼容端点(需带特定回调参数),若没有则只能采用前两种方案。
内容的提问来源于stack exchange,提问作者user19354065

