问题描述
我正尝试将一些HTTP请求从我的angular.js应用程序发送到服务器,但是我需要解决一些CORS错误.
I'm trying to send some HTTP requests from my angular.js application to my server, but I need to solve some CORS errors.
使用以下代码发出HTTP请求:
The HTTP request is made using the following code:
functions.test = function(foo, bar) {
return $http({
method: 'POST',
url: api_endpoint + 'test',
headers: {
'foo': 'value',
'content-type': 'application/json'
},
data: {
bar:'value'
}
});
};
第一次尝试以一些CORS错误告终.因此,我在PHP脚本中添加了以下几行:
The first try ended up with some CORS errors. So I've added the following lines to my PHP script:
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT');
header('Access-Control-Allow-Headers: X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding, X-Auth-Token, content-type');
第一个错误现在已消除.
The first error is now eliminated.
现在,Chrome的开发者控制台向我显示以下错误:
Now the Chrome's developer console shows me the following errors:
423ef03a:1 XMLHttpRequest无法加载 http://localhost:8000/test .飞行前的响应具有无效的HTTP 状态码400
423ef03a:1 XMLHttpRequest cannot load http://localhost:8000/test. Response for preflight has invalid HTTP status code 400
并且网络请求看起来像我预期的一样(HTTP状态400
也是预期的):
and the network request looks like I expected (HTTP status 400
is also expected):
我无法想象如何解决问题(以及如何理解),为什么请求将以OPTIONS
的身份在localhost上以POST
的身份发送到远程服务器.有解决方案如何解决这个奇怪的问题吗?
I can't imagine how to solve the thing (and how to understand) why the request will send on localhost as OPTIONS
and to remote servers as POST
. Is there a solution how to fix this strange issue?
推荐答案
OPTIONS
请求被称为 飞行前请求 ,它是 跨域资源共享(CORS).浏览器使用它来检查是否允许来自特定域的请求,如下所示:
The OPTIONS
request is so called pre-flight request, which is part of Cross-origin resource sharing (CORS). Browsers use it to check if a request is allowed from a particular domain as follows:
- 浏览器要发送一个请求,比方说一个
POST
内容类型为application/json
的请求 - 所以首先,它发送飞行前
OPTIONS
请求 - 如果服务器回复非2XX状态响应,则浏览器将不会发送实际请求(因为他现在知道仍然会拒绝该请求)
- 如果浏览器对飞行前请求得到
HTTP 200 OK
响应,它将发送实际请求,在您的情况下为POST
- The browser wants to send a request, let's say a
POST
request with theapplication/json
content type - So first, it sends the pre-flight
OPTIONS
request - If the server replies with a non-2XX status response, the browser won't send the actual request (because he knows now that it would be refused anyway)
- If the browser got a
HTTP 200 OK
response to the pre-flight request, it sends the actual request,POST
in your case
理论
简单请求
浏览器不是在某些情况下发送飞行前请求,这些请求称为简单请求,在以下情况中使用条件:
Theory
Simple requests
Browsers are not sending the pre-flight requests in some cases, those are so-called simple requests and are used in the following conditions:
-
Accept
-
Accept-Language
-
Content-Language
-
Content-Type
(但请注意以下附加要求) -
DPR
-
Downlink
-
Save-Data
-
Viewport-Width
-
Width
Accept
Accept-Language
Content-Language
Content-Type
(but note the additional requirements below)DPR
Downlink
Save-Data
Viewport-Width
Width
-
application/x-www-form-urlencoded
-
multipart/form-data
-
text/plain
application/x-www-form-urlencoded
multipart/form-data
text/plain
此类请求是直接发送的,如果它与CORS规则不匹配,服务器会简单地成功处理该请求或以错误答复.无论如何,响应都将包含CORS标头Access-Control-Allow-*
.
Such requests are sent directly and the server simply successfully processes the request or replies with an error in case it didn't match the CORS rules. In any case, the response will contain the CORS headers Access-Control-Allow-*
.
浏览器会发送飞行前请求,最常见的情况是:
Browsers are sending the pre-flight requests if the actual request doesn't meet the simple request conditions, the most usually:
- 使用
- 自定义内容类型,例如
application/xml
或application/json
等 - 请求方法不是
GET
,HEAD
或POST
-
POST
方法的内容类型不同于application/x-www-form-urlencoded
,multipart/form-data
或text/plain
- custom content types like
application/xml
orapplication/json
, etc., are used - the request method is other than
GET
,HEAD
orPOST
- the
POST
method is of an another content type thanapplication/x-www-form-urlencoded
,multipart/form-data
ortext/plain
您需要确保对飞行前请求的响应具有以下属性:
You need to make sure that the response to the pre-flight request has the following attributes:
- 成功的HTTP状态代码,即
200 OK
- 标头
Access-Control-Allow-Origin: *
(通配符*
允许来自任何域的请求,您当然可以在此处使用任何特定域来限制访问)
- successful HTTP status code, i.e.
200 OK
- header
Access-Control-Allow-Origin: *
(a wildcard*
allows a request from any domain, you can use any specific domain to restrict the access here of course)
从另一面看,服务器可以简单地通过发送对具有以下属性的飞行前请求的响应来拒绝CORS请求:
From the other side, the server may refuse the CORS request simply by sending a response to the pre-flight request with the following attributes:
- 不成功的HTTP代码(即
2XX
以外的其他代码) - 成功的HTTP代码(例如
200 OK
),但没有任何CORS标头(例如Access-Control-Allow-*
)
- non-success HTTP code (i.e. other than
2XX
) - success HTTP code (e.g.
200 OK
), but without any CORS header (i.e.Access-Control-Allow-*
)
请参见文档在Mozilla开发人员网络上或例如有关详细信息,请 HTML5Rocks的CORS教程.
See the documentation on Mozilla Developer Network or for example HTML5Rocks' CORS tutorial for details.
因此,在您的情况下,存在正确的标头,您只需确保飞行前响应的HTTP状态代码为200 OK
或其他成功的HTTP状态代码(2XX
).
So, in your case, the proper header is present, you just have to make sure the pre-flight response's HTTP status code is 200 OK
or some other successful one (2XX
).
这篇关于来自Angular的HTTP请求以OPTIONS而不是POST的形式发送的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!