在ajax跨域名通常情况下大家是无法去改服务器配置的,只有从脚本下手了。方法很简单,用php做一个中间键,如:
PHP代码: header("Content-Type: text/xml; charset=gb2312"); echo file_get_contents($info);
todd提供的解决方法: 设置document.domain。 前提条件:两个页面同属于一个基础域(例如都是xxx.com,或是xxx.com.cn);同一协议(例如都是http);同一端口(例如都是80)。 方法:设置两个页面的document.domain都设置为自己所在的基础域名。 例子:aaa.xxx.com里面的一个页面需要调用bbb.xxx.com里的一个对象,则将两个页面的document.domain都设置为xxx.com,就可以了。
跨浏览器、跨域的Ajax工具: Modello.ajax
问题 如果你曾经在使用 XMLHTTPRequest 的时候遇到过以下问题,那么 Modello.ajax 可以帮你解决。
XMLHTTPRequest 在各种浏览器和版本上面使用方法不一样 XMLHTTPRequest 的使用方法过于繁琐 XMLHTTPRequest 不能跨域获取资源 JavaScript 中缺乏 urlparse 、urljoin 这样的 URL 分析工具
urlget 函数 Modello.ajax 是使用 Modello 框架编写的,用于 JavaScript 联网操作的类库。它实现跨浏览器调用,跨域获取资源,并且使用起来非常简单。请看下面的例子: phperz~com
// 指定 jsproxy.php 的位置 Define('URLGET_PROXY', '/jsproxy.php');
// 回调函数 var callback = function(header, body, url, chunnel) { alert(header); alert(body); }
var url = 'http://www.baidu.com'; var data = ''; var chunnel = null; var headers = []; var urlget = Class.get('modello.ajax.Urllib').urlget;
// 异步方式 urlget(url, data, callback, chunnel, headers);
// 同步方式 // var ret = urlget(url, data, null, chunnel, headers); // ret[0]: Response header // ret[1]: Response body
// 如果请求失败,返回 false。 // 如果成功,异步调用返回 true,同步调用返回回复的 header 和 body内容。 上面的代码执行结果就是先 alert HTTP 的头部信息,然后 alert 百度主页的 HTML 代码。下面来解释一下 url, data, callback, chunnel, headers 这五个参数的含义: phperz~com
url:字符串,资源的 URL 地址。 data:字符串,POST 数据。如果为空,则使用 GET 方法获取。 callback:函数,异步回调函数。如果为空,则等待直至结果返回。回调函数接收四个参数:header, body, url, chunnel。header 是回复的头部信息,body 是回复的体部内容,url 是当前请求的URL,chunnel 是调用时指定的命名通道。 chunnel:字符串,命名通道。如果为空,则重用或者新建已有的通道。如果指定了通道的名字,而该通道正在被其它请求使用时,函数返回 false。 headers:数组,请求头部。当要获取的资源需要某些特殊的头部的时候(例如 User-Agent 或者 Referer ),可以在这个参数中加入。
urlget 各个参数的设计是按照使用频率来排列的。在大部分情况下,url, data, callback 这三个参数已经满足要求。建议尽量使用异步方式,因为同步方式虽然是起来更方便,但是它会使浏览器挂起来,等待结果的返回。在这期间,浏览器不会响应任何事件,屏幕也不会重画,给用户很不好的感受。在使用异步方式的时候,回调函数中 url 这个输入参数可以帮助你识别当前请求到底是那个 URL,这对于用一个回调函数处理多个请求的回复的情况是很有用的。
再说说 chunnel 这个参数,如果你想在客户端发出多个异步请求,而又想这些请求按照一定的顺序一个一个执行,这时候 chunnel 发挥作用。请看下面例子: phperz.com
// 向服务器发出心跳请求。 var url = '...'; var data = 'action=heartbeat'; var callback = function(){}; var chunnel = 'heartbeat'; var timer = setInterval(function() { urlget(url, data, callback, chunnel); }, 1000); 上面例子中,如果忽略 chunnel 参数,当第一个心跳请求的执行时间超过一秒,这时,第二个心跳请求不会等待第一个请求执行完成就会发送出去。这可能不是服务器所期望的行为,另外对网络资源来说也是一种浪费。但如果设置了 chunnel 参数,第二个心跳请求不会发出去,因为这个 chunnel 正在被第一个请求占用,urlget 函数会返回 false。
jsproxy 如果要获取的资源在本域,使用 Modello.ajax 就足够了。如果要跨域获取,还需要一个放在本域的 proxy 来配合(为什么?XMLHTTPRequest 的使用有一个安全域限制。当要获取放在其它域的资源,IE会弹出安全警告,firefox 和 opera 则会出错)。在该版本中,给出一个 php 的 proxy 实现:jsproxy.php。只要将 jsproxy.php 放到本域的服务器上,然后在调用 urlget 之前插入下面一行代码:
// 指定 jsproxy.php 的位置 Define('URLGET_PROXY', '/jsproxy.php'); phperz.com 下面来说明一下这个 jsproxy 的实现原理。它是一个 cgi 程序,接受两个 POST 参数:url 和 data。url 是目标资源的 URL 地址,data 是POST 数据。如果 data 为空,jsproxy使用 GET 方法获取资源,否则使用 POST 方法获取资源。jsproxy 会把获取到的回复的头部信息和体部内容全部转发给 urlget。但在转发之前,jsproxy 会进行如下处理:从回复的头部和体部查找回复的 Content-Type 和字符集。对于没有 Content-Type 的回复,jsproxy 一律返回 404 给 urlget。对于没有字符集的回复,jsproxy自动加上 DEFAULT_CHARSET(这个参数在 jsproxy.php 里面设置)。jsproxy 还会对 Content-Type 进行过滤,在 jsproxy.php 里设置 ALLOW_CONTENT_TYPE 这个参数可以达到这个目的。欢迎有兴趣的朋友编写其他语言版本的 jsproxy:)
Request 类 一般情况下,urlget 已经足够了。但如果你想做一些更细致的联网操作,可以使用或者扩展这个类:modello.ajax.Request。urlget 其实就是它的封装。modello.ajax.Request 类的 API 如下:
// 类的路径 var Request = Class.get('modello.ajax.Request');
// 创建实例 // 参数: // url: 字符串,资源的 URL 地址 php程序员站 // method: 字符串,获取的方法。GET 或者 POST // data:字符串,POST的数据 var request = new Request(url, method, data);
// 设置 URL request.seturl(/blog/url);
// 设置方法 request.setMethod(method);
// 设置 POST 数据 request.setData(data);
// 设置异步回调函数 request.setHandler(handler);
// 设置请求头部 // 参数: // key: 字符串,名称 // value: 字符串,值 request.setHeader(key, value);
// 加入一行头部数据 request.addHeader(header);
// 打开请求 // 参数: // async: 布尔值,是否异步。默认为 false request.open(async);
// 中断请求 request.abort();
// 返回当前请求的状态 // 总共有 5 种状态(字符串) // Uninitialized: 未初始化,对象已建立,但是尚未初始化(尚未调用open方法) // Loading: 初始化,对象已建立,尚未调用send方法 // Loaded: 发送数据,send方法已调用,但是当前的状态及http头未知 // Interactive: 数据传送中,已接收部分数据,因为响应及http头不全,这时通过responseBody和responseText获取部分数据会出现错误 php程序员之家 // Complete: 完成,数据接收完毕,此时可以通过通过responseBody和responseText获取完整的回应数据 // 上面的解释来自 www.xmlhttp.cn request.getState();
// 回复的状态码 request.getStatus();
// 回复状态码对应的字符串解释 request.getStatusText();
// 回复头部 request.getHeader(key);
// 所有回复头部(不包含状态行) request.getAllHeaders();
// 原始回复头部(包含状态行) request.getRawHeader();
// 回复体部 request.getText();
// 回复体部的 XML 形式 request.getXML();
// 重置请求(清掉所有之前设置的请求头部) request.reset(); Connection 类 如果你只是想得到一个跨浏览器的 XMLHTTPRequest 对象,可以使用如下方法。
// 跨浏览器的 XMLHTTPRequest 对象 var conn = Class.get('modello.ajax.Connection').get(); urlparse 和 urljoin 函数 除了上面的用于联网的类,Modello.ajax 还提供两个 URL 分析函数:
// URL 分析函数 var urlparse = Class.get('modello.ajax.Urllib').urlparse; www.phperz.com var url = 'http://kenxu:kenxu@www.ajaxwing.com:80/index.php?s=modello#top'; var ret = urlparse(url); // 这时候 // ret.scheme: http // ret.user: kenxu // ret.pass: kenxu // ret.host: www.ajaxwing.com // ret.port: 80 // ret.path: /index.php // ret.query: s=modello // ret.flagment = top
// URL 合并函数 var urljoin = Class.get('modello.ajax.Urllib').urljoin; var ret = urljoin(base, url); // 如果这时 // base: http://www.ajaxwing.com/images // url: index.php // 那么 // ret: http://www.ajaxwing.com/images/index.php phperz~com // 如果 url 改成 // url: /index.php // 那么 // ret: http://www.ajaxwing.com/index.php // 如果 url 改成 // url: http://www.baidu.com/index.php // 那么 // ret: http://www.baidu.com/index.php // 就是这个原理
// 如果 base 为空,返回 url // 如果 url 为空,返回 base
总结 Modello.ajax.Urlget 和 Modello.ajax.Connection 都是工具类,提供静态方法,使用前不需创建它的实例;Modello.ajax.Request 是一个基础类,使用前要先创建实例。
|
|
[收藏此页] [打印本页] [返回顶部] |
|
|
|
|
|
|
|
|
|