来自Angular的HTTP请求以OPTIONS而不是POST的形式发送 [英] HTTP request from Angular sent as OPTIONS instead of POST

查看:545
本文介绍了来自Angular的HTTP请求以OPTIONS而不是POST的形式发送的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正尝试将一些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:

angular.js:12011选项 http://localhost:8000/test (匿名 功能)

angular.js:12011 OPTIONS http://localhost:8000/test (anonymous function)

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请求被称为

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:

  1. 浏览器要发送一个请求,比方说一个POST内容类型为application/json的请求
  2. 所以首先,它发送飞行前 OPTIONS请求
  3. 如果服务器回复非2XX状态响应,则浏览器将不会发送实际请求(因为他现在知道仍然会拒绝该请求)
  4. 如果浏览器对飞行前请求得到HTTP 200 OK响应,它将发送实际请求,在您的情况下为POST
  1. The browser wants to send a request, let's say a POST request with the application/json content type
  2. So first, it sends the pre-flight OPTIONS request
  3. 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)
  4. 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:

  • 允许的方法之一:
    • GET
    • HEAD
    • POST
  • One of the allowed methods:
    • GET
    • HEAD
    • POST
  • 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/xmlapplication/json
  • 请求方法不是GETHEADPOST
  • POST方法的内容类型不同于application/x-www-form-urlencodedmultipart/form-datatext/plain
  • custom content types like application/xml or application/json, etc., are used
  • the request method is other than GET, HEAD or POST
  • the POST method is of an another content type than application/x-www-form-urlencoded, multipart/form-data or text/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的形式发送的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆