跨域ajax请求不能在iOS模拟器中使用Phonegap执行



我刚刚开始使用Phonegap和一般的移动开发,并且我试图调用$.ajax(…)来做任何当从iOS模拟器或iOS设备运行时-但是我的小应用程序在从浏览器或Ripple模拟器(http://ripple.incubator.apache.org/)运行时都工作得很好。

此外,我已经熟悉了CORS,并且我的测试似乎表明,我的请求/响应标头已正确设置为跨域客户机-服务器通信。使用Safari WebInspector的JS调试器逐步执行(并监视服务器的Apache日志),我已经能够确定对xhr.send()的调用从未实际执行过。

一旦我意识到这一点,我就从公式中删除了jQuery,以防我不正确地设置$.ajax()请求,并且我使用下面的代码创建CORS请求(从这里获得:http://www.html5rocks.com/en/tutorials/cors/)

在这两种情况下(使用和不使用jQuery),我注意到在调试器中调用xhr.open(…)之后,xhr.open(…)的值。Status和xhr。statusText都设置为"[Exception: DOMException]",我假设这是阻止xhr.send()执行的原因。

另外,config.xml包含以下行:

<access origin="*" />
下面是创建和执行请求的代码:
// Create the XHR object.
function createCORSRequest(method, url) {
  var xhr = new XMLHttpRequest();
  if ("withCredentials" in xhr) {
    // XHR for Chrome/Firefox/Opera/Safari.
    xhr.open(method, url, true);
  } else if (typeof XDomainRequest != "undefined") {
    // XDomainRequest for IE.
    xhr = new XDomainRequest();
    xhr.open(method, url);
  } else {
    // CORS not supported.
    xhr = null;
  }
  return xhr;
}
// Helper method to parse the title tag from the response.
function getTitle(text) {
  return text.match('<title>(.*)?</title>')[1];
}
// Make the actual CORS request.
function makeCorsRequest() {
  // All HTML5 Rocks properties support CORS.
  var url = 'http://server.mylocalhost/api/action?arg1=foo';
  var xhr = createCORSRequest('GET', url);
  if (!xhr) {
    alert('CORS not supported');
    return;
  }
  // Response handlers.
  xhr.onload = function() {
    var text = xhr.responseText;
    var title = getTitle(text);
    alert('Response from CORS request to ' + url + ': ' + title);
  };
  xhr.onerror = function() {
    alert('Whoops, there was an error making the request.');
  };
  xhr.send();
}

注意:上面在makeCorsRequest()中指定的url反映了我在应用程序中所针对的url的实际结构。

我设置:

  • ajax请求两端的完全控制
  • 本地开发,客户端和服务器使用独立的apache虚拟主机(例如http://server.mylocalhost和http://mobile.mylocalhost)
  • 所有内容的最新版本(Phonegap/Cordova, Xcode, Ripple, Chrome, Safari, Jquery, OSX/Mavericks等)
我觉得我一定错过了一些非常基本的东西…什么好主意吗?

另外,我不喜欢使用JSONP。

这原来是网络(DNS)层的问题。事实证明,Xcode iOS模拟器忽略了主机的/etc/hosts文件,并且似乎没有等效的方法来控制模拟器环境中的DNS。因此,据我所知,使用基于名称的虚拟主机在本地开发机器上进行开发是不可能的……这似乎是一个相当荒谬的限制。

由于iOS模拟器显然确实知道如何找到"localhost",我通过将以下行添加到虚拟主机的VirtualHost容器中来解决我的问题,虚拟主机是我的目标API端点(在适当的Apache配置文件中):

ServerAlias localhost

然后我将makeCorsRequest()中的url更改为以下形式:

var url = 'http://localhost/api/action?arg1=foo';

在基于jquery的版本中进行类似的更改也有效。

可能有其他更好的方法来解决这个令人难过的限制,但是现在这个修复已经允许我回到实际关注我的应用程序。

最新更新