I'm trying to setup AngularJS to communicate with a cross-origin resource where the asset host which delivers my template files is on a different domain and therefore the XHR request that angular performs must be cross-domain. I've added the appropriate CORS header to my server for the HTTP request to make this work, but it doesn't seem to work. The problem is that when I inspect the HTTP requests in my browser (chrome) the request sent to the asset file is an OPTIONS request (it should be a GET request).

我不确定这是AngularJS中的一个bug,还是我需要配置一些东西。根据我的理解,XHR包装器不能做出一个OPTIONS HTTP请求,所以看起来就像浏览器在执行GET请求之前试图弄清楚是否“允许”首先下载资产。如果是这种情况,那么我是否需要与资产主机一起设置CORS头(Access-Control-Allow-Origin: http://asset.host…)?


当前回答

同一份文件说

与简单请求(上面讨论过)不同,“预飞行”请求首先向另一个域上的资源发送一个HTTP OPTIONS请求头,以确定发送实际请求是否安全。跨站点请求就像这样被预先传送,因为它们可能会对用户数据产生影响。特别是,如果出现以下情况,请求将被预飞:

它使用的方法不是GET或POST。同样,如果POST用于发送内容类型不是application/x-www-form-urlencoded、multipart/form-data或text/plain的请求数据,例如,如果POST请求使用application/ XML或text/ XML向服务器发送XML有效负载,则该请求是预飞的。 它在请求中设置自定义报头(例如,请求使用一个报头,如X-PINGOTHER)

当原始请求是没有自定义头的Get请求时,浏览器不应该像现在这样发出Options请求。问题是它生成了一个头部X-Requested-With,它强制Options请求。关于如何删除此标头,请参阅https://github.com/angular/angular.js/pull/1454

其他回答

你的服务必须用这样的头来回答OPTIONS请求:

Access-Control-Allow-Origin: [the same origin from the request]
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: [the same ACCESS-CONTROL-REQUEST-HEADERS from request]

这里有一个好医生:http://www.html5rocks.com/en/tutorials/cors/#toc-adding-cors-support-to-the-server

注意:不确定它是否适用于最新版本的Angular。

原:

也可以覆盖OPTIONS请求(仅在Chrome中测试):

app.config(['$httpProvider', function ($httpProvider) {
  //Reset headers to avoid OPTIONS request (aka preflight)
  $httpProvider.defaults.headers.common = {};
  $httpProvider.defaults.headers.post = {};
  $httpProvider.defaults.headers.put = {};
  $httpProvider.defaults.headers.patch = {};
}]);

如果你正在使用一个nodeJS服务器,你可以使用这个库,它对我来说很好https://github.com/expressjs/cors

var express = require('express')
  , cors = require('cors')
  , app = express();

app.use(cors());

之后你可以进行NPM更新。

这解决了我的问题:

$http.defaults.headers.post["Content-Type"] = "text/plain";

不知怎的,我通过改变来解决它

<add name="Access-Control-Allow-Headers" 
     value="Origin, X-Requested-With, Content-Type, Accept, Authorization" 
     />

to

<add name="Access-Control-Allow-Headers" 
     value="Origin, Content-Type, Accept, Authorization" 
     />