2012年5月3日星期四

jQuery Cross-Domain Ajax w/XML = NO WAY!

今天製作Blogger小工具時,原以為會很順利的。
Google Blogger API Reference Guide看到可以用GET方式得到Comments的XML。

當然二話不說,打開Aptana Studio立即工作。
基於jQuery Ajax,不到一小時已經搞定,在本機試行,沒有問題。
沾沾自喜地心想: (那會難得到我?)


那就把程式碼Copy & Paste至Blogger的HTML/JavaScript小工具,儲存,看一看。
OMFG~竟然什麼都沒有,打開IE9的F12 Developer Tool看看出現大概是這樣的Error。
XMLHttpRequest cannot load XXX.
Origin XXX is not allowed by Access-Control-Allow-Origin.
上Google搜尋一下,原來是Google防止Cross-Domain Request帶出的問題。

根據一些討論區答案,解決方法是轉用JSONP,因為Google API 伺服器不支援CORS (Cross-origin resource sharing)

其實Google API 既有提供JSON,jQuery亦可以解讀,當然問題其實老早已解決。

但我就是有點不服氣,深入理解一下CORS。

按照網上的高手建議,
可以在Http Headers (PHP/ASP.NET)或jQuery Ajax中加入:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Authorization

之後又有人建議對jQuery設定
$.support.cors = true;
crossDomain: true;

當然統統試過都沒有用,因為主導權是在Server那邊,要是好像Google般不容許Cross-Domain Request的話,無論如何在Headers出什麼古惑都沒有用。

以下就是我的Blogger Recent Comments的XML版本。
http://webapp.heliohost.org/html/blogger_recent_comments.htm
Save As另存新檔後,在本機用Browser打開,是沒有問題的。

但在線上看,就會出現我說的問題。
當然現在問題已經解決,我已經轉用JSONP方式去實現。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <title>blogger_recent_comments</title>
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
  <script type="text/javascript">
   function contains(arr, obj) {
    for(var i = 0; i < arr.length; i++) {
     if(arr[i].toLowerCase() == obj.toLowerCase() && arr[i].length == obj.length)
      return true;
    }
   }

   if( typeof String.prototype.startsWith != 'function') {
    String.prototype.startsWith = function(str) {
     return this.indexOf(str) == 0;
    };
   }

   $(document).ready(function() {
    var feedurl = "http://www.blogger.com/feeds/880240131395666753/comments/default";
    var maxcount = 10;
    var minlength = 10;
    var exclude_name = new Array("&#36948;MiNG");

    $.support.cors = true;
    $.ajax({
     type : "GET",
     url : feedurl,
     dataType : "xml",
     crossDomain : true,
     headers : {
      "GData-Version" : "2"
     },
     success : function(responseData, textStatus, jqXHR) {
      var cnt = 0;
      var html = "";
      $(responseData).find('entry').each(function() {
       var title = $(this).find("title").text();
       var content = $(this).find('content').text();
       var url = $(this).find("link[rel='alternate']").attr('href');
       var authorname = $(this).find("author").find('name').text();

       if(!contains(exclude_name, authorname) && !content.startsWith('[...]') && title.length >= 10) {
        html += "<span style='font-family:Arial;color:#333;font-size:11px;font-weight:bold;'>" + authorname + " &#35498; : </span><br />" + "<span style='font-family:Arial;color:#666;font-size:11px;'>" + title + "</span><br /><br />";
        cnt++;
       }
       if(cnt == maxcount)
        return false;
      });
      var dom = $(html);
      $('#recent_comments').append(dom);
     },
     error : function(responseData, textStatus, errorThrown) {
      console.log(textStatus);
     }
    });
   });
  </script>
 </head>
 <body>
  <div id="recent_comments"></div>
 </body>
</html>

沒有留言:

發佈留言