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

路杨有2个域名,[easun.org](http://easun.org) [easunlee.org](http://easunlee.org) 统统指向同一个地址。
而小站的 [blog 主页](http://easun.org/blog) 的分页获取是通过 [jQuery](http://jquery.com/) 的AJAX完成的。 见抓图。 index_15_6_5.png ###核心代码为自写。如下: function 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结构, 返回的数据大致为 {"error":null,"result":{"next_url":"下一页的地址","content":"本页展示数据"}} 如果出错,则在本页面打开没有 `format=js` 参数的完整 HTML 版本。 ## 但是,这个脚本还是有问题的。 如果以域名 访问,则毫无问题, 一旦用 则基本上不能完成。 不用说后期路杨打算给后台设置不同的子域名。 原因很简单: **ajax 不能跨域**。(当然某些BT 的 ie 版本正常跨域,汗。) ###有没有办法解决这个问题呢? 研究了一番,发现使用 [jQuery](http://jquery.com/) 的 JSONP 方式即可完成。 即让后台返回的数据为 mycallback( {"error":null,"result":{"next_url":"下一页的地址","content":"本页展示数据"}} ); ###当然需要修改核心代码,让 $.ajax 工作在 JSONP 下: function 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](http://www.perl.org/) 脚本, 命名为 jsonp.cgi: #!/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核心代码: function 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*/ } , }); } 到此,修改完成。