Php 用JavaScript替代跨域请求

Php 用JavaScript替代跨域请求,php,javascript,ajax,.htaccess,cgi,Php,Javascript,Ajax,.htaccess,Cgi,我在一个名为kopernikus.science.net的服务器上有一个JavaScript,它想访问另一个名为galileo.science.net的服务器上的文件。下面是我想到的一个玩具示例: code residing on http://kopernikus.science.net/makecalendar.js : var request = new XMLHttpRequest(); request.open("GET","galil

我在一个名为
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>";
驻留在计算机上的代码http://kopernikus.science.net/makecalendar.js :
var request=new XMLHttpRequest();
打开(“GET”,“galileo.science.net/calendar”,false);
请求发送(空);
document.getElementById(“日历”).innerHTML=
“+request.responseText.split('\n')[0]+”;
不幸的是,由于现代web浏览器的“同源策略”,脚本被禁止访问不同域上的数据

当然,我的问题是:

我怎样才能访问远程文件

允许使用JavaScript之外的解决方案,如镜像有问题的文件或调整
.htaccess
。我有什么选择?在web服务器上,哪一个需要最少的权限

该文件是vcalendar格式的日历,定期更改。我在共享主机上,没有系统管理员权限,但我可以运行PHP和CGI脚本,并可以更改
.htaccess
文件的某些部分。

一些选项:

  • 如果您控制服务器,并且您的用户将使用最新的web浏览器,则可以使用。遗憾的是,IE7或更低版本中没有CORS支持。在IE8中,它是存在的,但您必须使用而不是
    XMLHttpRequest
    (其他浏览器,如Chrome和Firefox,使用
    XMLHttpRequest
    完全透明地处理COR)
  • 如果没有,您可以使用,它适用于所有浏览器
  • 您可以使用来指定这两个页面(如果它们确实是同一
    science.net
    域的子域)位于同一来源。这在浏览器中运行得很好,但它的缺点是,在访问目标文档之前,必须先将其加载到窗口(可能是隐藏的iframe),因为目标文档还必须设置
    document.domain
    (以表明它希望与您合作)
  • 另一种选择,对于公共事务,是
  • 如果所有这些都失败了,您唯一的实际选择是在您查询的服务器上有一个代理脚本,然后使用服务器端代码从其他域查询资源(因为此限制仅适用于客户端)
  • 它们大致按照我使用它们的顺序列出。例如,如果您控制服务器并知道您的客户端将使用最新浏览器,则使用CORS;如果没有,请查看JSONP(尽管从您下面的评论来看,您可能不能);如果不是这两个,也许
    document.domain
    就是答案;等等,等等,将列表向下移动到最后的选择(代理)。

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

    服务器应返回如下内容:

    callCallback({"some":"JSONString"});
    
    不幸的是,由于"同源", 现代网络浏览器的“策略” 禁止脚本访问 不同域上的数据

    但你能做的就是使用它

    脚本和JSONP请求不可用 受同一原产地政策约束 限制

    
    img{高度:100px;浮点:左;}
    $.getJSON(“http://api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?",
    {
    标签:“猫”,
    tagmode:“任何”,
    格式:“json”
    },
    功能(数据){
    $.each(data.items,function(i,item){
    $("
    

    作为现代浏览器支持(Internet Explorer 8 +,Firefox 3.5 +,Safari 4 +,Chrome)的另一个注释。

    < P>这是一个非常著名的问题,JSONP就是这个问题的解决方案。你可以在谷歌上加上一大堆的信息。你可以把这当作JSONP使用jjQuery和jQuery的例子。

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

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

    如果您显示的域名是真名,您应该能够使用
    document.domain
    :JSONP是否要求文件
    galileo.science.net/calendar
    采用JSON格式?不幸的是,不是,我无法控制。@Heinrich:是的。对于JSONP,您请求的基本上是一个脚本文件,而我t必须以特定的方式设置。如果您无法控制所请求的内容,您将看到选项1(
    document.domain
    ,如果它们确实是同一域的子域),\2(CORS,如果服务器允许任何来源),选项4或新添加的选项5。你能举一个如何使用
    document.domain
    的例子吗?只需在JavaScript中添加
    document.domain=“science.net”
    。@Heinrich:是的,就是这么简单。更多(至少是一点)在MDC页面上:请注意,必须在两个页面上都执行此操作,以表明他们的合作意向。这要求您将计划连接的HTML加载到iframe或其他内容中,而不是通过XHR。我必须承认,我忘记了双方都必须执行
    document.domain
    操作。我在列表中对其进行了降级。:-)不幸的是,我正在访问的文件不是JSON格式。我无法控制它。那么JSON-p将无法工作(但您可以自己代理它?)。或者您也可以使用YQL来处理跨域请求=>。YQL将为您执行代理。我无法控制
    galileo.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
        }
    }