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请求绝不是AngularJS的错误,这是跨源资源共享标准要求浏览器的行为。请参考此文件:https://developer.mozilla.org/en-US/docs/HTTP_access_control,其中“概述”部分说:
The Cross-Origin Resource Sharing standard works by adding new HTTP
headers that allow servers to describe the set of origins that are
permitted to read that information using a web browser. Additionally,
for HTTP request methods that can cause side-effects on user data (in
particular; for HTTP methods other than GET, or for POST usage with
certain MIME types). The specification mandates that browsers
"preflight" the request, soliciting supported methods from the server
with an HTTP OPTIONS request header, and then, upon "approval" from
the server, sending the actual request with the actual HTTP request
method. Servers can also notify clients whether "credentials"
(including Cookies and HTTP Authentication data) should be sent with
requests.
提供一个适用于所有WWW服务器的通用解决方案是非常困难的,因为设置取决于服务器本身和你打算支持的HTTP动词。我鼓励您阅读这篇优秀的文章(http://www.html5rocks.com/en/tutorials/cors/),其中有更多关于服务器需要发送的确切头部的详细信息。
在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();
});
OPTIONS请求绝不是AngularJS的错误,这是跨源资源共享标准要求浏览器的行为。请参考此文件:https://developer.mozilla.org/en-US/docs/HTTP_access_control,其中“概述”部分说:
The Cross-Origin Resource Sharing standard works by adding new HTTP
headers that allow servers to describe the set of origins that are
permitted to read that information using a web browser. Additionally,
for HTTP request methods that can cause side-effects on user data (in
particular; for HTTP methods other than GET, or for POST usage with
certain MIME types). The specification mandates that browsers
"preflight" the request, soliciting supported methods from the server
with an HTTP OPTIONS request header, and then, upon "approval" from
the server, sending the actual request with the actual HTTP request
method. Servers can also notify clients whether "credentials"
(including Cookies and HTTP Authentication data) should be sent with
requests.
提供一个适用于所有WWW服务器的通用解决方案是非常困难的,因为设置取决于服务器本身和你打算支持的HTTP动词。我鼓励您阅读这篇优秀的文章(http://www.html5rocks.com/en/tutorials/cors/),其中有更多关于服务器需要发送的确切头部的详细信息。
以下是我在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