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…)?


当前回答

如果你正在使用Jersey的REST API,你可以这样做

你不需要改变你的webservices实现。

我会解释Jersey 2.x

1)首先添加一个ResponseFilter,如下所示

import java.io.IOException;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;

public class CorsResponseFilter implements ContainerResponseFilter {

@Override
public void filter(ContainerRequestContext requestContext,   ContainerResponseContext responseContext)
    throws IOException {
        responseContext.getHeaders().add("Access-Control-Allow-Origin","*");
        responseContext.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");

  }
}

2)然后在web.xml中,在jersey servlet声明中添加如下内容

    <init-param>
        <param-name>jersey.config.server.provider.classnames</param-name>
        <param-value>YOUR PACKAGE.CorsResponseFilter</param-value>
    </init-param>

其他回答

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

<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" 
     />

在pkozlowski的评论中有完美的描述。 我有工作解决方案与AngularJS 1.2.6和ASP。NET Web Api,但当我将AngularJS升级到1.3.3时,请求失败。

Solution for Web Api server was to add handling of the OPTIONS requests at the beginning of configuration method (more info in this blog post): app.Use(async (context, next) => { IOwinRequest req = context.Request; IOwinResponse res = context.Response; if (req.Path.StartsWithSegments(new PathString("/Token"))) { var origin = req.Headers.Get("Origin"); if (!string.IsNullOrEmpty(origin)) { res.Headers.Set("Access-Control-Allow-Origin", origin); } if (req.Method == "OPTIONS") { res.StatusCode = 200; res.Headers.AppendCommaSeparatedValues("Access-Control-Allow-Methods", "GET", "POST"); res.Headers.AppendCommaSeparatedValues("Access-Control-Allow-Headers", "authorization", "content-type"); return; } } await next(); });

这解决了我的问题:

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

对于Angular 1.2.0rc1+,你需要添加一个resourceUrlWhitelist。

1.2:发布版他们增加了一个escapeForRegexp函数,所以你不再需要转义字符串。你可以直接添加url

'http://sub*.assets.example.com/**' 

确保为子文件夹添加**。下面是一个适用于1.2版本的jsbin: http://jsbin.com/olavok/145/edit


1.2 rc:如果你仍然使用rc版本,Angular 1.2 rc1的解决方案是这样的:

.config(['$sceDelegateProvider', function($sceDelegateProvider) {
     $sceDelegateProvider.resourceUrlWhitelist(['self', /^https?:\/\/(cdn\.)?yourdomain.com/]);
 }])

下面是一个适用于1.2 rc1的jsbin示例: http://jsbin.com/olavok/144/edit


Pre 1.2:对于旧版本(参考http://better-inter.net/enabling-cors-in-angular-js/),您需要在配置中添加以下2行:

$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];

下面是一个jsbin的例子,它适用于1.2之前的版本: http://jsbin.com/olavok/11/edit

你的服务必须用这样的头来回答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