Javascript 来自Angular的HTTP请求作为选项而不是POST发送

Javascript 来自Angular的HTTP请求作为选项而不是POST发送,javascript,php,angularjs,http,cors,Javascript,Php,Angularjs,Http,Cors,我试图从angular.js应用程序向服务器发送一些HTTP请求,但我需要解决一些CORS错误 HTTP请求使用以下代码进行: functions.test = function(foo, bar) { return $http({ method: 'POST', url: api_endpoint + 'test', headers: { 'foo': 'value', 'content-t

我试图从angular.js应用程序向服务器发送一些HTTP请求,但我需要解决一些CORS错误

HTTP请求使用以下代码进行:

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脚本中添加了以下行:

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');
现在消除了第一个错误

现在,Chrome的开发者控制台向我显示以下错误:

js:12011选项(匿名) 功能)

423ef03a:无法加载1 XMLHttpRequest . 飞行前的响应具有无效的HTTP 状态代码400

并且网络请求看起来与我预期的一样(HTTP status
400
也是预期的):

我无法想象如何解决(以及如何理解)为什么请求会以
OPTIONS
的形式发送到本地主机,并以
POST
的形式发送到远程服务器。有没有办法解决这个奇怪的问题?

TL;answer博士 解释
选项
请求被称为,它是的一部分。浏览器使用它来检查特定域是否允许请求,如下所示:

  • 浏览器希望向特定URL发送请求,比如使用
    application/json
    内容类型的
    POST
    请求
  • 首先,它将飞行前
    选项
    请求发送到同一URL
  • 以下内容取决于飞行前请求的响应HTTP状态代码:
    • 如果服务器以非
      2XX
      状态响应进行响应,浏览器将不会发送实际请求(因为他现在知道无论如何都会被拒绝)
    • 如果服务器以
      HTTP 200 OK
      (或任何其他
      2XX
      )响应进行响应,浏览器将发送实际请求,在您的情况下为
      POST
  • 解决方案 因此,在您的情况下,存在正确的标头,您只需确保飞行前请求的响应HTTP状态代码是
    200 OK
    或其他成功的(
    2XX


    详细说明 浏览器在某些情况下不发送飞行前请求,这些请求称为简单请求,在以下情况下使用:

    • 允许的方法之一: -
      GET
      -
      HEAD
      -
      POST
    • 除了用户代理自动设置的头(例如,连接、用户代理等),仅允许手动设置的头如下:
      • 接受
      • 接受语言
      • 内容语言
      • 内容类型
        (但请注意以下附加要求)
      • DPR
      • 下行链路
      • 保存数据
      • 视口宽度
      • 宽度
    • 内容类型标题的唯一允许值为:
      • application/x-www-form-urlencoded
      • 多部分/表单数据
      • text/plain
    • 没有在请求中使用的任何
      XMLHttpRequestUpload
      对象上注册事件侦听器;可以使用
      XMLHttpRequest.upload
      属性访问这些文件
    • 请求中未使用任何
      ReadableStream
      对象
    这样的请求直接发送,服务器只是成功地处理请求,或者在不符合CORS规则的情况下返回一个错误。在任何情况下,响应都将包含CORS头
    访问控制允许-*

    如果实际请求不满足简单的请求条件,浏览器将发送飞行前请求,最常见的情况是:

    • 使用自定义内容类型,如
      application/xml
      application/json
    • 请求方法不是
      GET
      HEAD
      POST
    • POST
      方法是另一种内容类型,而不是
      application/x-www-form-urlencoded
      multipart/form data
      text/plain
    您需要确保对飞行前请求的响应具有以下属性:

    • 成功的HTTP状态代码,即
      200 OK
    • header
      访问控制允许来源:
      (通配符
      *
      允许来自任何域的请求,您当然可以使用任何特定域来限制此处的访问)
    从另一方面来说,服务器可以通过发送具有以下属性的对飞行前请求的响应来拒绝CORS请求:

    • 非成功HTTP代码(即除
      2XX
      之外)
    • 成功HTTP代码(例如
      200 OK
      ),但没有任何CORS头(即
      Access Control Allow-*

    有关详细信息,请参见or示例。

    我在编写Angular 2应用程序时遇到了一个非常类似的问题,该应用程序使用节点服务器作为API

    因为我在本地机器上开发,所以当我试图从Angular应用程序发布到API时,我不断遇到跨源标题问题

    如下所示设置标头(在节点服务器中)对GET请求有效,但我的PUT请求不断向数据库发送空对象

    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');
    
    阅读之后,我意识到飞行前请求向我的服务器发送了空白数据,这就是为什么我的DB条目为空,所以我在NODE JS服务器中添加了这一行:

      if (req.method == "OPTIONS")
        {
            res.writeHead(200, {"Content-Type": "application/json"});
            res.end();
        }
    

    所以现在我的服务器忽略了飞行前的请求(并返回状态200,让浏览器知道一切都是groovy…),这样,真正的请求就可以通过了,我得到了发布到数据库中的真实数据

    对于spring boot应用程序,要启用cors请求,请在各自的控制器上使用
    @CrossOrigin(origins=“*”,maxAge=3600)

    只要把

    if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
    header("HTTP/1.1 200 ");
    exit;}