【问题标题】:Why does a cross-domain angularjs $http.post request fail when a XMLHttpRequest succeeds?XMLHttpRequest成功时,为什么跨域angularjs $http.post请求失败?
【发布时间】:2013-03-07 13:58:33
【问题描述】:

我正在尝试使用来自 Angular(版本 1.0.5)webapp 的应用程序密钥和令牌来练习 Trello API。服务器似乎正确配置为处理CORS。来自enable cors 的带有http://test-cors.org 的测试请求按预期工作。

当我在我的一个角度控制器中发出发布请求时:

$http.post(url).success(function(data) {
  $scope.server_resp = data;
});

我收到 请求标头字段 Content-Type is not allowed by Access-Control-Allow-Headers 错误。 (尽管如下所示,Access-Control-Allow-Origin 设置为“*”)。为什么要加这个header,能去掉吗?

XMLHttpRequest

当我使用原始 XMLHttpRequest 发出相同的请求时,它会成功。以下是 XMLHttpRequest 的标头:

Request Method:POST
Status Code:200 OK

Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:0
Host:api.trello.com
Origin:http://192.168.0.125:9000
Referer:http://192.168.0.125:9000/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22

Response
Access-Control-Allow-Methods:GET, PUT, POST, DELETE
Access-Control-Allow-Origin:*
Cache-Control:max-age=0, must-revalidate, no-cache, no-store
Content-Length:563
Content-Type:application/json
Date:Mon, 18 Mar 2013 02:49:37 GMT
Expires:Thu, 01 Jan 1970 00:00:00
X-Powered-By:Express
X-Server-Time:1363574977568

Angular $http.post

以下是 Angular 发起请求的标头。请注意,浏览器发出了飞行前 OPTIONS 请求:

Request Method:OPTIONS
Status Code:200 OK

Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:accept, origin, content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:api.trello.com
Origin:http://192.168.0.125:9000
Referer:http://192.168.0.125:9000/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22

Response
Access-Control-Allow-Methods:GET, PUT, POST, DELETE
Access-Control-Allow-Origin:*
Content-Length:0
Content-Type:text/html; charset=utf-8
Date:Mon, 18 Mar 2013 02:51:00 GMT
X-Powered-By:Express

有没有办法配置 Angular 的请求标头以允许上面的 $http.post() 代码工作?

【问题讨论】:

  • 这是因为响应来自另一个域,并且它们在服务来自其他域的请求时有自己的规则。
  • 你可以尝试$http.jsonp()从另一个域获得响应
  • @Abilash 因为我想做一个帖子,jsonp 不是一个选项(我记得它只用于获取请求)。
  • 我对 CORS 的了解并不如我所愿,但我注意到您的(预检?)Angular 响应定义了允许的内容类型:“text/html; charset=utf-8”。您的 XHR 响应返回 Content-Type:“application/json”。在我看来,问题不是 CORS,而是数据类型不匹配。
  • 大卫,你找到解决方案了吗?我仍在寻找这个问题的答案:(

标签: angularjs


【解决方案1】:

服务器不接受“content-type”标头,默认情况下会为 Angular $http POST 请求添加(请参阅$http doc)。您可以尝试将其从 $http 配置中删除。在你的控制器中注入 $httpProvider,然后这可能会起作用:

delete $httpProvider.defaults.headers.post['Content-type']

您可能还必须尝试使用​​“内容类型”,我不确定要使用的情况。

【讨论】:

    【解决方案2】:

    将 headers 参数添加到 $http 就可以了。

              var config = {
                method: 'POST',
                url: 'your url',
                headers: {
                  'Content-Type': undefined
               },
               data: {
                  "channel": "#fun-and-game",
                  "username": $scope.question.title,
                  "text": $scope.question.text,
                  "icon_emoji": ":ghost:"
              },
           };
    
          $http(config).success(function(data) {
             $scope.server_resp = data;
          }).error(function(response) {
    
          });
    

    欲了解更多信息,请查看angularjs $http docs

    【讨论】:

    • 感谢@Olatunde Garuba。在尝试了太多方法后,它也解决了我的问题。
    • 也适合我。
    【解决方案3】:

    根据这个角度pull request,可以通过删除 X-Requested-With 来使 CORS 工作,这会导致飞行前 OPTIONS 请求:

    App.config(['$httpProvider', function($httpProvider) {
        delete $httpProvider.defaults.headers.common["X-Requested-With"];
    }
    

    请注意,我没有亲自尝试过,但一位同事必须删除标头才能使他的 CORS 请求正常工作。

    【讨论】:

      【解决方案4】:

      我刚刚遇到了类似的问题,问题是我弄错了网址。我发布到 1/cards/actions/createCard 因为我错过了文档。即使标题等看起来正确,我也遇到了与访问控制相关的错误。发布到 1/cards 创建了一张卡片,这正是我想要的。

      【讨论】:

        【解决方案5】:

        这对我有用

        $http({
              method  : "POST",
              url     : url,
              data    : $.param({key: 'value', key2 : 'value'}),
              headers : { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }
                        })
        

        【讨论】:

          【解决方案6】:

          为避免此问题,请在服务器端创建一个函数来捕获“OPTIONS”并返回 true。一些事情如下。

              /**
               * @url OPTIONS /
               */
              public function options()
              {
                  return;
              }
          

          【讨论】:

            猜你喜欢
            • 2014-03-29
            • 2013-01-17
            • 1970-01-01
            • 1970-01-01
            • 2016-03-15
            • 2015-05-25
            • 2011-12-23
            • 2017-12-27
            • 2015-01-28
            相关资源
            最近更新 更多