xmlhttp跨域访问

15 views
Skip to first unread message

zhangfan xu

unread,
Sep 13, 2006, 9:52:58 AM9/13/06
to Technology_DB
如何用Squid来实现Ajax跨域代理

什么是Ajax跨域代理?

玩Ajax的应该知道我在说什么:)
简单说就是因为浏览器的安全限制,你不能直接获取你站点以外的xml文档。

为什么用Squid来做?

你完全可以自己写一个代理小程序,比如用php,这方面的资料网上很多。
Squid是一个应用非常广泛、功能强大的代理服务器软件,用它自然是为了获得高效。

需要哪些软件?

Lighttpd(Apache)、Squid、squirm。
我这里以lighttpd为例,你完全可以用apache来代替。
这里介绍一下squirm,这是一款为squid量身定做的redirector程序,支持
正规表达式
,至于什么是redirector下面的工作原理你会知道它的作用。
系统平台:理论上支持上述软件的应该都可以(比如选择常见的linux),我这里以freebsd为例。

工作原理

用Lighttpd(Apache)的proxy模块作前端代理,把特定url的请求发送到squid,比如把
/service/proxy/*/http://othersite.com/abc.xml
这样的请求发送给squid来处理。

squid通过squirm这个redirector对url进行修正(相当于url
rewrite),通过squirm的配置文件我们可以把上述url地址重定向为
http://othersite.com/abc.xml
,这个过程对浏览器是透明的完全由squid完成。squid获取
http://othersite.com/abc.xml
后返回给浏览器,这样我们就实现了跨域,在Ajax应用中你如果要获取其他站点的内容就在url前加上
/service/proxy/*/ 即可。

关键配置

相关软件的基本配置网上很容易找到参考,我就不罗嗦了,下面给出关键的配置。

Lighttpd -
lighttpd.conf,比如我们的squid将工作在6666端口,就作如下配置

$HTTP["url"] =~ "^/service/proxy/" {
proxy.server = (
"" => (
(
"host" => "127.0.0.1",
"port" => 6666
)
)
)
}

Squid - squid.conf

http_port 6666
redirect_program /usr/local/bin/squirm
redirect_children 5
redirect_rewrites_host_header on
httpd_accel_host virtual
httpd_accel_with_proxy on
httpd_accel_uses_host_header on

squirm
- squirm.conf 主要指定redirector的匹配规则文件的位置

begin
network 0.0.0.0/0
log /var/squid/logs/squirm-private-match.log
abort-log /var/squid/logs/squirm-private-abort.log
pattern common.patterns all
end

- common.patterns 这里的匹配规则文件是 common.patterns

regex ^.*/service/proxy/\*/(.*)$ \1


我不知道我们每个人是否都有各自的命运
或者只是随意的在风中飘逝 但我想或许那都是对的

zhangfan xu

unread,
Sep 13, 2006, 9:54:51 AM9/13/06
to Technology_DB
跨域Ajax工具: Modello.ajax
2006-04-18 21:33 by kenxu
问题
Ajax是个好东西,但使用起来却不是那么方便。问题总结如下:

在各种浏览器上的创建方式和使用方法不一致
各个浏览器对响应的缓存策略有所不同
浏览器存在跨域获取限制
前两个问题可以通过封装 XMLHTTPRequest
对象来解决,第三个问题的解决方法有很多中,兼容性和移植性比较好的就是在本域服务器上放置一个中转
proxy 。Modello.ajax 就是提供这套解决方案的工具集。

安装
下载 Modello 和 Mdello.ajax
解压并将 modello.js, modello.ajax.js, jsproxy.php
这三个文件放到你的服务器任意文档目录中
在 html 页面中包含 modello.js 和 modello.ajax.js
这两个脚本文件
urlget 方法
Modello.ajax 使用起来非常的简单,请看下面例子:

// 设置跨域中转 proxy 路径Define('URLGET_PROXY',
'/jsproxy.php'); // 强大的 urlget 方法var urlget =
Class.get('modello.ajax.Urllib').urlget; var url = '...'; // 同步 GET
方法获取var response = urlget(url); // 同步 POST 方法获取var
data = '...';var response = urlget(url, data); // 异步 POST
方法获取var callback = function (response) { // ...}var ret =
urlget(url, data, callback); // 设置请求头部var headers =
["User-Agent: Modello.ajax's urlget"];var ret = urlget(url, data,
callback, headers); // 使用命名通道var chunnel = '...';var ret =
urlget(url, data, callback, headers, chunnel); // 使用 Response
对象if (response.getStatus() == 200) {
alert(response.getText());}// 设置跨域中转 proxy 路径
Define('URLGET_PROXY', '/jsproxy.php');

// 强大的 urlget 方法
var urlget = Class.get('modello.ajax.Urllib').urlget;

var url = '...';

// 同步 GET 方法获取
var response = urlget(url);

// 同步 POST 方法获取
var data = '...';
var response = urlget(url, data);

// 异步 POST 方法获取
var callback = function (response) {
// ...
}
var ret = urlget(url, data, callback);

// 设置请求头部
var headers = ["User-Agent: Modello.ajax's urlget"];
var ret = urlget(url, data, callback, headers);

// 使用命名通道
var chunnel = '...';
var ret = urlget(url, data, callback, headers, chunnel);

// 使用 Response 对象
if (response.getStatus() == 200) {
alert(response.getText());
}

urlget 各个参数的解释如下:

url:目标资源的 URL 地址。
data:POST 数据。如果 data 为空,则使用 GET 方法获取。

callback:异步获取回调函数。如果 callback
为空,则使用同步获取。
headers:附加请求头部。这是一个数组,每一项为字符串,设置一行头部,字符串末尾不可以带回车换行。

chunnel:命名通道。用于重用某个连接通道。
urlget 的返回值:

如果是同步获取,成功返回 Response 对象,失败返回
false。如果是异步获取,成功返回
true,并且在获取后调用回调函数,失败返回
false。如果指定了命名通道,但该通道正在被其它请求占用,同步、异步都统一返回
false。

回调函数的参数:

response:Response 对象。
chunnel:调用时指定的命名通道。
Response 对象
Response
对象用于访问响应的各个数据项。它提供接口如下:

response.getStatus(); // HTTP
响应码(整数)response.getStatusText(); //
响应码的字面解释response.getHeader(key); // 由 key
指定的响应的头部数据response.getAllHeaders(); //
响应的所有头部数据(不包含状态行)response.getRawHeader();
// 响应的原样头部数据(包含状态行)response.getText();
// 响应的体部数据response.getXML(); //
响应的体部数据格式化为 Xml Document
对象response.getStatus(); // HTTP 响应码(整数)
response.getStatusText(); // 响应码的字面解释
response.getHeader(key); // 由 key 指定的响应的头部数据
response.getAllHeaders(); //
响应的所有头部数据(不包含状态行)
response.getRawHeader(); //
响应的原样头部数据(包含状态行)
response.getText(); // 响应的体部数据
response.getXML(); // 响应的体部数据格式化为 Xml
Document 对象

大部分情况下,使用 urlget
函数足可以应付,并且它是可以跨浏览器,跨域使用的。如果你想做一些更底层的操作,Modello.ajax
为你提供两个跨浏览器使用的基类:Connection 和 Request

Connection 类
这是一个静态类,提供跨浏览器的方法返回一个
XMLHTTPRequest 对象。使用方法如下:

/* * 成功返回一个跨浏览器版本的 XMLHTTPRequest 对象, *
失败返回 null。 */var conn =
Class.get('modello.ajax.Connection').get();/*
* 成功返回一个跨浏览器版本的 XMLHTTPRequest 对象,
* 失败返回 null。
*/
var conn = Class.get('modello.ajax.Connection').get();

Request 类
这是对 XMLHTTPRequest
对象的封装,提供更加易用的接口并解决浏览器对响应缓存的问题,但不具备跨域获取功能。Request
提供的属性和方法如下:

/* * 类的路径 */var Request = Class.get('modello.ajax.Request'); /*
* 创建实例 * url, method, data 均为可选参数 */var request =
new Request([url[, method[, data]]]); /* * 设置 URL
*/request.setURL(url); /* * 设置获取方法。目前支持:GET,
POST, HEAD */request.setMethod(method); /* *
设置获取方法。目前支持:GET, POST, HEAD
*/request.setData(data); /* * 设置回调函数 *
回调函数的原型为: * var callback = function (response) {};
*/request.setHandler(handler); /* * 设置请求头部
*/request.setHeader(key, value); /* * 增加请求头部
*/request.addHeader(header); /* * 发送请求 * async 为
true,使用异步方式 * 默认使用同步方式 *
调用成功,同步方式返回 response 对象,异步方式返回
true * 调用失败,统一返回 false */request.open([async]); /* *
查询当前请求的状态 *
返回一个字符串描述,可能为: *
Uninitialized:未初始化 * Loading:初始化 *
Loaded:发送数据 * Interactive:数据传送中 *
Complete:完成 */request.getState(); /* * 返回当前使用的
Connection 对象 */request.getConnection(); /* * 返回 Response
对象 * 如果当前的请求状态不为 Complete,返回 null
*/request.getResponse(); /* * 中止当前请求 */request.abort(); /*
* 清理所有请求头部 */request.reset(); /* *
除了上面的方法,还可以对 Request
对象设置事件处理函数 * 总共有下面几种事件 */
request.onException = function() {};request.onLoading = function()
{};request.onLoaded = function() {};request.onInteractive = function()
{};request.onComplete = function() {};/*
* 类的路径
*/
var Request = Class.get('modello.ajax.Request');

/*
* 创建实例
* url, method, data 均为可选参数
*/
var request = new Request([url[, method[, data]]]);

/*
* 设置 URL
*/
request.setURL(url);

/*
* 设置获取方法。目前支持:GET, POST, HEAD
*/
request.setMethod(method);

/*
* 设置获取方法。目前支持:GET, POST, HEAD
*/
request.setData(data);

/*
* 设置回调函数
* 回调函数的原型为:
* var callback = function (response) {};
*/
request.setHandler(handler);

/*
* 设置请求头部
*/
request.setHeader(key, value);

/*
* 增加请求头部
*/
request.addHeader(header);

/*
* 发送请求
* async 为 true,使用异步方式
* 默认使用同步方式
* 调用成功,同步方式返回 response
对象,异步方式返回 true
* 调用失败,统一返回 false
*/
request.open([async]);

/*
* 查询当前请求的状态
* 返回一个字符串描述,可能为:
* Uninitialized:未初始化
* Loading:初始化
* Loaded:发送数据
* Interactive:数据传送中
* Complete:完成
*/
request.getState();

/*
* 返回当前使用的 Connection 对象
*/
request.getConnection();

/*
* 返回 Response 对象
* 如果当前的请求状态不为 Complete,返回 null
*/
request.getResponse();

/*
* 中止当前请求
*/
request.abort();

/*
* 清理所有请求头部
*/
request.reset();

/*
* 除了上面的方法,还可以对 Request
对象设置事件处理函数
* 总共有下面几种事件
*/

request.onException = function() {};
request.onLoading = function() {};
request.onLoaded = function() {};
request.onInteractive = function() {};
request.onComplete = function() {};

jsproxy
对于跨域调用,Modello.ajax
采用在本域服务器设置一个中转 proxy 的方式。使用
proxy
方式可以不用对个别浏览器进行特殊设置,不用依赖具体的服务器,并且具备扩展能力等优点。随
Modello.ajax 工具集提供的 proxy 用 php 写成,可运行 php
的服务器都可以安装。proxy
也可以用其它语言编写,Modello.ajax
有计划在后续版本中提供 python 版的
jsproxy。下面来描述 jsproxy
的设计,有需要的朋友可以参考来实现其它语言版本的
jsproxy。

jsproxy 接收三个 POST 参数:url, data, headers。url
为目标资源的URL地址;data
为POST数据,如果为空则使用 GET 方法获取资源;headers
附加的请求头部数据。jsproxy
根据这些参数去获取目标资源,然后将收到的响应头部和响应体部全部转发给请求者。jsproxy
收到的参数是由 Modello.ajax 发出的,字符集为
UTF-8,处理的时候要注意这点。jsproxy
获取到的响应的字符集有很多种可能的,在转发响应之前
jsproxy
应该自动检测出当前响应的字符集,并在转发的响应头部指明。如果忽律这个步骤,请求者收到的响应有可能是乱码。

urlparse, urljoin 函数
urlparse, urljoin 这样的 URL
处理函数在其它脚本语言中很常见,但在 JavaScript
中却没有。Modello.ajax 提供了这两个函数,前面提到的
urlget
函数内部就使用了这两个函数。下面来解释他们的用法:

/* * urlparse:URL 分析函数 */var url =
'http://user:pass@host:port/path?query#flagment';var ret =
Class.get('modello.ajax.Urllib').urlparse(url);// 这时候// ret.user
== 'user'// ret.pass == 'pass'// ret.host == 'host'// ret.post ==
'post',默认为 80// ret.path == 'path',以 '/' 开头// ret.query
== 'query'// ret.flagment == 'flagment' /* * urljoin:合并两个 URL
*/var url1 = 'http://www.example.com/about/about.html';var url2 =
'/index.html';var url = Class.get('modello.ajax.Urllib').urljoin(url1,
url2);// 这时候// url == 'http://www.example.com/index.html'


http://sourceforge.net/project/showfiles.php?group_id=164137&package_id=185772

http://sourceforge.net/project/showfiles.php?group_id=164137&package_id=187232

Reply all
Reply to author
Forward
0 new messages