繁体   English   中英

用JavaScript代替跨域请求

[英]Substitute for Cross-domain request with JavaScript

我在名为kopernikus.science.net的服务器上有一个JavaScript,它想要访问名为galileo.science.net的不同服务器上的文件。 这是我想到的一个玩具示例:

code residing on  http://kopernikus.science.net/makecalendar.js :

    var request = new XMLHttpRequest();
    request.open("GET","galileo.science.net/calendar", false);
    request.send(null);
    document.getElementById("calendar").innerHTML =
        "<div>" + request.responseText.split('\n')[0] + "</div>";

遗憾的是,由于现代Web浏览器的“相同原始策略”,禁止脚本访问不同域上的数据。

当然,我的问题是:

我怎么能访问远程文件?

允许使用JavaScript以外的解决方案,例如镜像相关文件或调整.htaccess 我有什么选择? 哪个需要Web服务器上的最少权限?

有问题的文件是vcalendar格式的日历,它会定期更改。 我在共享主机上,没有sysadmin权限,但我可以运行PHP和CGI脚本,并可以更改.htaccess文件的某些部分。

一些选择:

  1. 如果您控制服务器并且您的用户将使用最新的Web浏览器,则可以使用CORS 遗憾的是,IE7或更低版​​本中没有CORS支持。 在IE8中,它就在那里,但你必须使用XDomainRequest而不是XMLHttpRequest (其他浏览器,如Chrome和Firefox,使用XMLHttpRequest完全透明地处理CORS)。
  2. 如果没有,您可以使用适用于所有浏览器的JSONP
  3. 您可以使用document.domain指定这两个页面(如果它们实际上是同一个science.net域的子域)位于同一个源中。 这在浏览器中运行良好,但它的缺点是您首先必须将目标文档加载到窗口(可能是隐藏的iframe)才能访问它,因为目标文档必须设置document.domain (以显示它想与你合作)。
  4. 对于公共事物,另一种替代方法是使用YQL作为代理
  5. 如果所有这些都失败了,您唯一真正的选择是在您查询的服务器上有一个代理脚本,然后使用服务器端代码从另一个域查询资源(因为此限制仅适用于客户端)。

这些大致按照我使用它们的顺序列出。 例如,如果您控制服务器并且知道您的客户将使用最新的浏览器,请使用CORS; 如果没有,请查看JSONP(虽然从下面的评论中,你可能不能); 如果不是其中任何一个,也许document.domain就是答案; 等等,在列表中工作到最后的选择(代理)。

遗憾的是,由于现代Web浏览器的“相同原始策略”,禁止脚本访问不同域上的数据。

但你能做的就是使用json-p

脚本和JSONP请求不受相同的源策略限制。

<!DOCTYPE html>
<html>
<head>
  <style>img{ height: 100px; float: left; }</style>
  <script src="http://code.jquery.com/jquery-1.4.4.js"></script>
</head>
<body>
  <div id="images">

</div>
<script>
$.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?",
  {
    tags: "cat",
    tagmode: "any",
    format: "json"
  },
  function(data) {
    $.each(data.items, function(i,item){
      $("<img/>").attr("src", item.media.m).appendTo("#images");
      if ( i == 3 ) return false;
    });
  });</script>

</body>
</html>

另外,现代浏览器支持CORS (Internet Explorer 8 +,Firefox 3.5 +,Safari 4+和Chrome)。

假设您可以在kopernikus.science.net上部署PHP,为什么不在那里代理它...

<?php
header('Content-Type: application/x-javascript');
print file_get_contents('http://galileo.science.net/calendar');

(当然,你可以在代理和客户端上简单地缓存它以减少网络噪音)

更新

如果你想缓存....

<?php
header('Content-Type: application/x-javascript');
define("CACHEDIR", '/tmp/webcache/');
$cache_time=14 * 24 * 60 * 60; // cache for 2 weeks
$key=sha1('http://galileo.science.net/calendar');

if (@filemtime(CACHEDIR . $key) > time() - $cache_time) { // cache good
    print file_get_contents(CACHEDIR . $key);
} else {  // cache stale
    $freshcopy=file_get_contents('http://galileo.science.net/calendar');
    print $freshcopy;
    if (!file_put_contents(CACHEDIR . $key, $freshcopy)) {
       // report a problem writing files
    }
}

使用JSONP 在javascript中,在页面中嵌入一个新的脚本元素,该页面具有另一个服务器的接口作为源。

服务器应返回如下内容:

callCallback({"some":"JSONString"});

这是一个众所周知的问题,JSONP是问题的解决方案。 你可以google并提供大量的信息。 您可以将此视为使用JSONP和使用jQuery的示例。

http://www.beletsky.net/2010/07/json-jsonp-and-same-origin-policy-issue.html

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM