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


当前回答

你的服务必须用这样的头来回答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 7(或5/6/7)和PHP作为API,并且仍然得到这个错误,尝试在端点(PHP API)中添加以下头选项。

 header("Access-Control-Allow-Origin: *");
 header("Access-Control-Allow-Methods: PUT, GET, POST, PUT, OPTIONS, DELETE, PATCH");
 header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization");

注意:只需要Access-Control-Allow-Methods。但是,我在这里粘贴了另外两个Access-Control-Allow-Origin和Access-Control-Allow-Headers,只是因为你需要正确地设置所有这些,以便Angular应用能够正确地与你的API对话。

希望这能帮助到一些人。

欢呼。

我放弃了解决这个问题。

我的IIS网络。config中有相关的“Access-Control-Allow-Methods”,我尝试在我的Angular代码中添加配置设置,但在花了几个小时试图让Chrome调用一个跨域JSON web服务后,我悲惨地放弃了。

最后,我添加了一个愚蠢的ASP。Net handler网页,让它调用JSON web服务,并返回结果。它在两分钟内就运行起来了。

下面是我使用的代码:

public class LoadJSONData : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/plain";

        string URL = "......";

        using (var client = new HttpClient())
        {
            // New code:
            client.BaseAddress = new Uri(URL);
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            client.DefaultRequestHeaders.Add("Authorization", "Basic AUTHORIZATION_STRING");

            HttpResponseMessage response = client.GetAsync(URL).Result;
            if (response.IsSuccessStatusCode)
            {
                var content = response.Content.ReadAsStringAsync().Result;
                context.Response.Write("Success: " + content);
            }
            else
            {
                context.Response.Write(response.StatusCode + " : Message - " + response.ReasonPhrase);
            }
        }
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

在我的Angular控制器中…

$http.get("/Handlers/LoadJSONData.ashx")
   .success(function (data) {
      ....
   });

我相信有一种更简单/更通用的方式来做这件事,但生命太短暂了…

这对我很有效,现在我可以继续做正常的工作了!!

对于一个带有API的IIS MVC 5 / Angular CLI(是的,我很清楚你的问题是Angular JS)项目,我做了以下工作:

网络。在<system. Config。网络服务器>节点

    <staticContent>
      <remove fileExtension=".woff2" />
      <mimeMap fileExtension=".woff2" mimeType="font/woff2" />
    </staticContent>
    <httpProtocol>
      <customHeaders>
        <clear />
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Headers" value="Content-Type, atv2" />
        <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS"/>
      </customHeaders>
    </httpProtocol>

global.asax.cs

protected void Application_BeginRequest() {
  if (Request.Headers.AllKeys.Contains("Origin", StringComparer.OrdinalIgnoreCase) && Request.HttpMethod == "OPTIONS") {
    Response.Flush();
    Response.End();
  }
}

这应该可以解决MVC和WebAPI的问题,而不需要做所有其他的事情。然后我在Angular CLI项目中创建了一个HttpInterceptor,它会自动添加相关的头信息。希望这能帮助有类似情况的人。

如果你正在使用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>

以下是我在ASP上修复这个问题的方法。网

First, you should add the nuget package Microsoft.AspNet.WebApi.Cors Then modify the file App_Start\WebApiConfig.cs public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.EnableCors(); ... } } Add this attribute on your controller class [EnableCors(origins: "*", headers: "*", methods: "*")] public class MyController : ApiController { [AcceptVerbs("POST")] public IHttpActionResult Post([FromBody]YourDataType data) { ... return Ok(result); } } I was able to send json to the action by this way $http({ method: 'POST', data: JSON.stringify(data), url: 'actionurl', headers: { 'Content-Type': 'application/json; charset=UTF-8' } }).then(...)

参考: 在ASP中启用跨源请求。NET Web API 2