【问题标题】:Dojo can't make a CORS request. jQuery canDojo 无法发出 CORS 请求。 jQuery可以
【发布时间】:2014-02-17 20:06:35
【问题描述】:

我已经设置了一个 dojo 模块来处理我的通信:

define(["dojo/request/xhr", "dojo/json"],
  function(xhr, JSON) {

  return {
    getJson: function(url) {
      return xhr.get(url, {handleAs:'json', headers: {"X-Requested-With": ""}});
    },
    postJson: function(url, postData) {
      return xhr(url, {
        method: 'POST',
        handleAs: "json",
        data: JSON.stringify(postData),
        headers: {"X-Requested-With": "", "Content-Type":"application/json"}
      })
    },
    getSecure: function(url, token) {
      return xhr.get(url, {handleAs:'json', headers: {"X-AUTH": token, "X-Requested-With": "", "Content-Type":"application/json" }});
    },
    postSecure: function(url, postData, token) {
      return xhr(url, {
        method: 'POST',
        handleAs: 'json',
        data: JSON.stringify(postData),
        headers: {"X-Requested-With": "", "Content-Type":"application/json", "X-AUTH": token}
      });
    }
  };

});

发送请求时,OPTIONS 几乎立即失败。我在 Postman 中尝试了请求,只是为了确保 API 运行良好。然后我一头雾水,用 jQuery 构建了一个快速测试:

$.ajax({
  url: 'https://someurl.url/auth/get_token',
  type: 'post',
  data: JSON.stringify({username:"user", password:"pass"}),
  contentType: 'application/json',
  dataType: 'json' ,
  xhrFields: {
    withCredentials: false
  },
  success: function(json) {
    console.log(json);
    $.ajax({
      url: 'https://someurl.url/api/service/' + json.results.somevalue,
      type: 'GET',
      headers: { 'X-AUTH': json.results.token },
      contentType: 'application/json; charset=utf-8',
      dataType: 'json' ,
      success: function(json) {
        console.log(json);

      },
      error: function (XMLHttpRequest, textStatus, errorThrown) {
        console.log("error :"+XMLHttpRequest.responseText);
      }


    });

  },
  error: function (XMLHttpRequest, textStatus, errorThrown) {
    console.log("error :"+XMLHttpRequest.responseText);
  }

效果很好。我知道 Dojo 大约一年前在发送“X-Requested-width”标头时遇到了问题,但我已经取消了它并且它没有尝试发送它。我正在拔头发,因为我真的不想将 jQuery 作为对我的应用程序的依赖项仅用于发出 Web 请求。 Dojo 应该能够做到这一点。那里有任何 Dojo 人知道如何完成这项工作吗?

【问题讨论】:

  • 问题可能与您的服务器有关。向我们展示请求标头,以及来自您的服务器的响应标头,因为尝试失败。
  • jquery 请求:imgur.com/RgV8ZBc 和 dojo 请求:imgur.com/5o1sdQC 对于图片,我深表歉意,我无法访问服务器。我能真正展示的只是请求在 jquery 中的工作方式以及服务器在 devtools 中的响应。
  • 您无需访问服务器即可提供实际的响应标头。您可以在客户端和服务器之间插入透明代理来准确记录这些。您不能相信浏览器会正确报告标头,或者根本不能相信 CORS 请求的响应没有正确确认 CORS 请求。由于只有请求标头和与 Dojo 一起发送的预检临时标头,很难说请求失败的原因。我猜,一旦您查看实际的请求和响应标头,所有这些都会非常清楚。
  • 如果您只对 HTTP 流量感兴趣,Wireshark 可能有点太低级了。我建议改用FiddlerCharles 之类的东西。我要离开这里过夜。以防万一你发布这些数据,我明天再回来看看,看看有没有其他人突然介入。
  • 感谢大家的帮助,最后发现它是一个格式错误的 URL。当我注意到正在创建另一个请求文件夹时,Charles DID 立即指出了这一点。

标签: ajax dojo xmlhttprequest cors


【解决方案1】:

您可以简单地使用 dojo/request/xhr 模块发出任何 HTTP 请求,例如 OPTIONS、GET、PUT、DELETE、CONNECT、PUT、HEAD、TRACE 等。

将 http 方法名称作为字符串传递(全部大写),如下所示,

require(['dojo/request/xhr'], function(xhr){
    xhr(url, {
        handleAs : "json",
        method : 'OPTIONS',
        data : formDataAsJson,
        headers : {
            'Content-Type' : 'application/json'
        }
    }).then(
        function(data) {
            console.log("response data is: "+ JSON.stringify(data));
        },
        function(err) {
            console.log("The err is: "+ JSON.stringify(err));
        },
        function(evt) {
            console.log("The evt is: "+ JSON.stringify(evt));
        }
    );
});

【讨论】:

    【解决方案2】:
              var syncCall = true;
              if(dojo.isFF)
                syncCall = false;
              xhr(url, { 
                method : 'GET',
                handleAs : 'json',
                withCredentials : true,
                sync  :  syncCall,
                headers : {
                  'X-XSRF-Token' : settings.XSRF_TOKEN,
                  'Content-Type' : 'application/json'
                }
    

    【讨论】:

      【解决方案3】:

      我对 dojo.xhrGet 有过类似的体验,而 'Content-Type': 'application/json' 是问题所在。我不得不更改它以假装我正在取回纯文本,以便它真正跨域工作,因此:

      dojo.xhrGet({
          url: url,
          headers: {
              'X-Requested-With': null,
              'Content-Type': 'text/plain'
          },
          load: function(responseText) {
              var results = JSON.parse(responseText);
          ...
          }
      });
      

      之后它跨域工作,并将结果视为 JSON 对象。

      【讨论】:

        【解决方案4】:

        空字符串与 null 不同。您需要将 X-Requested-With 设置为 null,而不是 "",以避免预检请求。没关系,除非您的服务器没有响应允许 X-Requested-With 标头,因为您无论如何都会发送自定义标头,这将始终触发预检。

        【讨论】:

        • 我试过空字符串和空字符串。结果相同。我意识到自定义标头“X-AUTH”正在触发预检,但 jquery 请求通过了预检。
        • 请注意,由于 Content-Type,即使没有 X-Requested-With 标头,此请求也会被预检。
        • 对,但由于我必须发送一个令牌(“X-AUTH”标头),我别无选择。我在 jQuery 示例中也是这样做的。
        • 是的,对于您的 getSecure 调用,X-AUTH 标头也将强制进行预检。请根据代理发布请求和响应标头。
        • 我已经在上面给你的回复中添加了它们。
        猜你喜欢
        • 1970-01-01
        • 2019-10-21
        • 2013-03-08
        • 1970-01-01
        • 1970-01-01
        • 2020-10-17
        • 2015-02-25
        • 2021-07-02
        • 2017-08-06
        相关资源
        最近更新 更多