[JQ+Perl]JQ AJAX跨域请求HTML/JS页面内容总结

路杨有2个域名,easun.org easunlee.org 统统指向同一个地址。
而小站的 blog 主页 的分页获取是通过 jQuery 的AJAX完成的。 见抓图。
index_15_6_5.png

核心代码为自写。如下:

codefunction ajax_get (url, mode,callback)
  {
   var sdiv = $("#search-results"); 
   if (!sdiv) return true; 
   $.ajax({ 
        url:url, 
        data: {'format':'js'}, 
         success: function(data){ 
             if ( data.error == null ){ 
                      if (mode == 'append')  sdiv.append(data.result.content);
                      else  sdiv.html(data.result.content); 
                      if (data.result.next_url) { next_url = data.result.next_url;  } 
                      else { $('#show-more').hide(); }  
                      return false; 
                   }else { location.href = url;return true;}                       
              }, 
              error:function(req, status, obj){ location.href = url; return true;}, 
              beforeSend: function(xh){  /*do sth before send*/   },   
              complete: function(xh){  /*do sth for complete*/    } , 
             }); 
     }

其中url 为本站后台地址,大致为:
http://easun.org/{path-to-mt}/mt-search.cgi?IncludeBlogs=2&archive_type=Index&template_id={main_index_tmp_id}&page={num}

加上format=js参数则为JSON结构, 返回的数据大致为

code{"error":null,"result":{"next_url":"下一页的地址","content":"本页展示数据"}}

如果出错,则在本页面打开没有 format=js 参数的完整 HTML 版本。

但是,这个脚本还是有问题的。

如果以域名 http://easun.org/blog/ 访问,则毫无问题, 一旦用 http://easunlee.org/blog/ 则基本上不能完成。 不用说后期路杨打算给后台设置不同的子域名。
原因很简单: ajax 不能跨域。(当然某些BT 的 ie 版本正常跨域,汗。)

有没有办法解决这个问题呢?

研究了一番,发现使用 jQuery 的 JSONP 方式即可完成。
即让后台返回的数据为

codemycallback( {"error":null,"result":{"next_url":"下一页的地址","content":"本页展示数据"}} ); 

当然需要修改核心代码,让 $.ajax 工作在 JSONP 下:

codefunction ajax_get (url, mode,callback)
{
  var sdiv = $("#search-results"); 
  if (!sdiv) return true; 
  $.ajax({ 
        url:url, 
        data: {'format':'js'}, 
        dataType: "jsonp",  /*定义dataType*/
        jsonpCallback:"mycallback", /*定义jsop 回调函数*/
         success: function(data){ 
             if ( data.error == null ){ 
                      if (mode == 'append')  sdiv.append(data.result.content);
                      else  sdiv.html(data.result.content); 
                      if (data.result.next_url) { next_url = data.result.next_url; } 
                      else { $('#show-more').hide(); }  
                      return false; 
                   }else { location.href = url;return true;}                       
              }, 
              error:function(req, status, obj){ location.href = url; return true;}, 
              beforeSend: function(xh){  /*do sth before send*/   },   
              complete: function(xh){  /*do sth for complete*/    } , 
             }); 
}   

不用担心返回的 JSONP 数据在 success: function(data) 中无法解析,只要定义了
dataType: "jsonp",jsonpCallback:"mycallback",success: function(data)中的 data 自动为 JSONP 中包含的 JSON数据。 而不是 JSONP 数据串。
现在的问题,是后台的 mt-search.cgi 不具备输出 JSONP 格式的能力, format=js 只能输出 JSON 格式,这个时候如果不想修改 mt 代码。则只能通过自己写的脚本(Perl)来中转了。

简单写下以下 Perl 脚本, 命名为 jsonp.cgi:

code#!/usr/bin/perl -w
use strict;
use CGI;
my $q = CGI->new;
print $q->header(
       -type    => 'text/javascript+json',
       -charset => 'utf-8',
        );

my $url = $q->param('url') || "http://easun.org/{path-to-mt}/mt-search.cgi?IncludeBlogs=2&archive_type=Index&template_id={main_index_tmp_id}&page=2&format=js";
my $jsonp = $q->param('callback') || 'mycallback';

&getcachefile($url,$jsonp) ;

sub getcachefile
{
 my ($url,$jsonp)= @_;
 $url .= '&format=js';
 require LWP::UserAgent;
 require HTTP::Request;
 my $ua = LWP::UserAgent->new;
 $ua->max_size(undef) if $ua->can('max_size');
 my $req = new HTTP::Request(GET => $url);
 my $resp = $ua->request($req);
 return unless $resp->is_success();
 my $result = $resp->content();
 print( "$jsonp(" . $result . ");\n" );
}
1;  

再次修改ajax核心代码:

codefunction ajax_get (url, mode,callback)
{
  var sdiv = $("#search-results"); 
  if (!sdiv) return true; 
  var newurl = 'http://easun.org/path-to-cgi/jsonp.cgi';
  $.ajax({ 
        url:newurl, 
        data: {'format':'js', 'url': url}, /*原来的url*/
        dataType: "jsonp",
        jsonpCallback:"mycallback",
         success: function(data){ 
             if ( data.error == null ){ 
                      if (mode == 'append')  sdiv.append(data.result.content);
                      else  sdiv.html(data.result.content); 
                      if (data.result.next_url) { next_url = data.result.next_url; } 
                      else { $('#show-more').hide(); }  
                      return false; 
                   }else { location.href = url;return true;}                       
              }, 
              error:function(req, status, obj){ location.href = url; return true;}, 
              beforeSend: function(xh){  /*do sth before send*/   },   
              complete: function(xh){  /*do sth for complete*/    } , 
             }); 
}    

到此,修改完成。