为何Browser fetch可正常运行,AngularJS $http服务却报CORS错误?
搞定AngularJS $http的403问题:和fetch差异的根源及解决办法
嘿,我之前也碰到过类似的问题,咱们来一步步拆解:
从你贴的错误信息和代码来看,核心问题出在**浏览器的CORS预请求(OPTIONS请求)**上,这也是AngularJS $http和fetch表现不一样的关键原因:
为什么两者表现不同?
- AngularJS的
$http服务有个默认行为:它会自动给所有请求加上X-Requested-With: XMLHttpRequest这个自定义请求头。加上这个头之后,浏览器会判定这不是"简单请求",必须先发送一个OPTIONS预请求到服务器,确认是否允许后续带自定义头的GET请求。如果你的后端(Saiku服务器)没配置好处理OPTIONS请求,或者不允许X-Requested-With这个头,就会返回403禁止访问。 - 而
fetch API默认不会加这个X-Requested-With头。虽然你带了Authorization头理论上也会触发预请求,但可能你的后端刚好允许不带X-Requested-With的OPTIONS请求,或者你在fetch里的配置刚好避开了这个问题,所以能正常工作。
怎么解决?
方法1:让AngularJS $http去掉默认的X-Requested-With头
最简单的办法就是在发起请求时,显式把这个头设为undefined,覆盖默认配置:
const $http = angular.element(document.body).injector().get('$http'); $http({ method: 'GET', url: 'http://192.168.1.126:8080/saiku/rest/saiku/admin/datasources/', headers: { 'Authorization': 'Basic YWRtaW46YWRtaW4=', // 去掉默认的X-Requested-With头 'X-Requested-With': undefined } })
如果你的项目里很多地方都用$http,也可以全局配置一次,一劳永逸:
angular.module('你的应用模块名').config(['$httpProvider', function($httpProvider) { // 删除全局默认的X-Requested-With头 delete $httpProvider.defaults.headers.common['X-Requested-With']; }]);
方法2:配置后端服务器,正确处理OPTIONS预请求
如果不能改前端代码,就得在Saiku服务器那边配置CORS规则,确保:
- 允许OPTIONS请求方法
- 允许的请求头包含
Authorization和X-Requested-With(如果保留默认头的话) - 指定允许的前端源(就是你的页面所在的域名/IP)
举个Java后端的例子(Saiku基于Java),可以加个CORS过滤器:
public class CorsFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; HttpServletRequest request = (HttpServletRequest) req; // 替换成你的前端域名/IP response.setHeader("Access-Control-Allow-Origin", "http://你的前端地址"); response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); response.setHeader("Access-Control-Allow-Headers", "Authorization, X-Requested-With, Content-Type"); response.setHeader("Access-Control-Max-Age", "3600"); // 处理OPTIONS请求直接返回200 if ("OPTIONS".equals(request.getMethod())) { response.setStatus(HttpServletResponse.SC_OK); return; } chain.doFilter(req, res); } }
方法3:核对fetch的实际请求配置
你可以打开浏览器开发者工具的Network面板,对比AngularJS请求和fetch请求的请求头差异,看看fetch是不是有特殊配置(比如mode: 'no-cors',不过这种模式下你拿不到响应内容),或者后端对fetch的请求有特殊权限。如果fetch能跑通,那方法1基本就能解决问题。
小提示
403错误大多是服务器权限控制的问题,所以优先看后端的CORS配置和OPTIONS请求处理逻辑。用Network面板抓包对比请求头,是快速定位问题的好办法。
内容的提问来源于stack exchange,提问作者Gabriel Rohden
相关产品推荐
相关产品推荐

