Angular 跨域请求 CORS 失败,但节点 http.get() 成功返回
Posted
技术标签:
【中文标题】Angular 跨域请求 CORS 失败,但节点 http.get() 成功返回【英文标题】:Angular Cross-Origin Request CORS failure, but node http.get() returns successfully 【发布时间】:2015-05-25 21:39:32 【问题描述】:我正在尝试使用 AngularJS 访问 API。我已经使用以下节点代码检查了 API 功能。这就排除了故障出在
var http = require("http");
url = 'http://www.asterank.com/api/kepler?query="PER":"$lt":1.02595675,"$gt":0.67125&limit=10';
var request = http.get(url, function (response)
var buffer = ""
response.on("data", function (chunk)
buffer += chunk;
);
response.on("end", function (err)
console.log(buffer);
console.log("\n");
);
);
我使用节点 http-server 运行我的 Angular 应用程序,并带有以下参数
"start": "http-server --cors -a localhost -p 8000 -c-1"
我的角度控制器如下所示
app.controller('Request', function($scope, $http)
// functional URL = http://www.w3schools.com/website/Customers_JSON.php
$scope.test = "functional";
$scope.get = function()
$http.get('http://www.asterank.com/api/kepler?query="PER":"$lt":1.02595675,"$gt":0.67125&limit=10',
params:
headers:
//'Access-Control-Allow-Origin': '*'
'Access-Control-Request-Headers' : 'access-control-allow-origin'
)
.success(function(result)
console.log("Success", result);
$scope.result = result;
).error(function()
console.log("error");
);
// the above is sending a GET request rather than an OPTIONS request
;
);
控制器可以解析 w3schools URL,但在传递 asterank URL 时它始终返回 CORS 错误。 我的应用在本网站(如下)上针对 CORS 建议的其他补救措施。
通过 Firefox 检查 GET 请求表明标头未添加到 GET 请求中。但除此之外,我不知道如何解决这个问题。感谢通过 Angular 学习的人的帮助。
我尝试过使用 $http.jsonp()。 GET 请求成功执行(通过网络),但 angular 方法返回 .error() 函数。
var app = angular.module('sliderDemoApp', ['ngSlider', 'ngResource']);
.config(function($httpProvider)
//Enable cross domain calls
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
);
【问题讨论】:
【参考方案1】:你应该明白一件简单的事情:尽管那些 http
模块看起来有些相似,但就 CORS 而言,它们是完全不同的野兽。
其实node.js http.get()
跟CORS没有关系。发出请求的是您的服务器 - 就像您在浏览器的位置栏中键入此 URL 并命令打开它时所做的一样。用户代理是不同的,是的,但一般过程是相同的:客户端访问位于外部服务器上的页面。
现在请注意与 Angular 的 $http.get()
的区别:客户端打开一个运行脚本的页面,该脚本尝试访问位于外部服务器上的页面。换句话说,这个请求在另一个页面的上下文中运行——位于它自己的域中。除非 external 服务器允许该域在 client 代码中访问它,否则这是不可能的 - 毕竟这就是 CORS 的意义所在。
有不同的解决方法:JSONP - 这基本上意味着将响应包装到函数调用中 - 是一种可能的方法。但它与其他解决方法具有相同的关键点 - external 服务器应该允许这种形式的通信。否则,您对 JSONP 的请求将被忽略:服务器发回常规 JSON,这在尝试将其作为函数调用处理时会导致错误。
底线:除非外部服务器愿意在这件事上进行合作,否则您将无法在客户端应用程序中使用其数据 - 除非您通过服务器传递此数据(其作用类似于代理)。
【讨论】:
谢谢,这确实有助于阐明为什么节点成功而角度无法访问它的机制。非常感谢您花时间详细说明差异【参考方案2】:Asterank 现在允许对其 API 的跨源请求。您无需再担心上面发布的这些解决方法。一个简单的 $http.get(http://www.asterank.com/api/kepler?query="PER":"$lt":1.02595675,"$gt":0.67125&limit=10') 现在可以工作了。不需要标头。我上周向他们发送了有关此问题的电子邮件,他们回复并配置了他们的服务器以允许所有源请求。
来自 Asterank 的确切电子邮件回复:“我刚刚为 Asterank 启用了 CORS(即 Access-Control-Allow-Origin *)。希望这会有所帮助!”
【讨论】:
【参考方案3】:昨天我遇到了与 CORS 类似的问题,我使用表单解决了这个问题,希望这会有所帮助。
.config(function($httpProvider)
delete $httpProvider.defaults.headers.common['X-Requested-With'];
$httpProvider.defaults.headers.common = ;
$httpProvider.defaults.headers.post = ;
$httpProvider.defaults.headers.put = ;
$httpProvider.defaults.headers.patch = ;
)
.controller('FormCtrl', function ($scope, $http)
$scope.data =
q: "test"//,
// z: "xxx"
;
$scope.submitForm = function ()
var filters = $scope.data;
var queryString ='';
for (i in filters)
queryString=queryString + i+"=" + filters[i] + "&";
$http.defaults.useXDomain = true;
var getData =
method: 'GET',
url: 'https://YOUSEARCHDOMAIN/2013-01-01/search?' + queryString,
headers:
'Content-Type': 'application/json; charset=utf-8'
;
console.log("posting data....");
$http(getData).success(function(data, status, headers, config)
console.log(data);
).error(function(data, status, headers, config)
);
)
<div ng-controller="FormCtrl">
<form ng-submit="submitForm()">
First names: <input type="text" name="form.firstname">
Email Address: <input type="text" ng-model="form.emailaddress">
<button>bmyutton</button>
</form>
</div>
似乎也可以与您在上面发布的网址一起使用..
对象:0.017dec:50.2413kmag:10.961KOI:72.01MSTAR:1.03Per:0.8374903RA:19.04529Row:31贸易:1.38RSTAR:1T0:64.57439TPLANET:1903TSTAR:5627UPER:0.0000015UT0:0.00026 P>
我还应该补充一点,在 chrome 中您需要 CORS plugin。我没有像角度那样深入研究这个问题。我发现一个基本的 html 可以绕过这些 CORS 限制,这只是一种解决方法,直到我有更多时间来理解这个问题。
【讨论】:
表单不是解决方法:除非您提到的插件已安装并激活,否则您将遇到同样的问题。 可以确认我添加了您提到的插件并且我的代码可以在没有使用表单解决方法的情况下运行,并且它的插件正在发挥作用。在实现必要的后端之前肯定是一个有用的技巧【参考方案4】:环顾四周。我为此找到的最佳本地解决方案是 npm 模块 CORS-anywhere。用它来创建AngularJS AWS Cloudsearch Demo。
【讨论】:
以上是关于Angular 跨域请求 CORS 失败,但节点 http.get() 成功返回的主要内容,如果未能解决你的问题,请参考以下文章
使用 Angular 和 NodeJs (CORS) 的跨域请求