簡體   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