// by redice 2009.8.21
// http://www.redicecn.cn/blogview.asp?Content_Id=185
// 想写点东西…
背景知识:域名解析中“传统URL转发”是不完整的,只能转发到特定的URL,而不能转发到特定URL下的其它目录和文件。
示例一:
我们将域名bbs.taoyard.com做“传统URL转发”到http://www.taoyard.com/bbs。这样我们通过访问http://bbs.taoyard.com 就能访问到
http://www.taoyard.com/bbs的页面。但是我们不能通过http://bbs.taoyard.com/index.asp?boardid=1
来访问 http://www.taoyard.com/bbs/index.asp?boardid=1。因为“传统URL”转发只能转发到特定URL,而不能转发到其下的目录和文件。
示例二:
公益组织“慈善厨房”的国际域名是www.yellowrivercharity.com,它们的虚拟主机是国外的,这家IDC的虚拟主机不支持绑定多个域名(只能绑定一个域名,呵呵,不知道用的什么服务器)。现在“慈善厨房”又申请了一个cn域名:test.soupkitchen.cn。他们想实现通过两个域名能访问到同样的内容,而且Web服务器必须要使用国外的那台虚拟主机。
“慈善厨房”将域名test.soupkitchen.cn做URL转发到www.yellowrivercharity.com,这样通过test.soupkitchen.cn可以访问到www.yellowrivercharity.com了。他们在中国对外公布了很多以test.soupkitchen.cn为域名的子网页,
例如 http://test.soupkitchen.cn/chinese/about(chn).asp,但是由于test.soupkitchen.cn不能转发www.yellowrivercharity.com下的子目录和子网页,因此那些地址都是无效的。
如何解决上面的问题呢?
我们需要一种能实现完整URL转发的机制。我想到了使用ISAPI Filter“域名重写”实现完整的URL转发。
(“域名重写”这个词可是我创造的,哈哈)。
实现其实很简单,只需要3步:(我们需要准备一个虚拟主机,新建一个呗,就叫“慈善厨房”吧)
(1)在Win2003 IIS 6.0下新建一个虚拟主机,称为“慈善厨房”,将域名test.soupkitchen.cn绑定其上。
(2)test.soupkitchen.cn做域名解析到202.117.112.10(上面“慈善厨房”虚拟主机使用的IP)。
(3)核心:安装“域名重写”的ISAPI Filter插件。
ok,这样就成功了。前两步都很简单。关键是第三步,我们要编写一个ISAPI Filter实现“域名重写”。
熟悉Filter的人都知道,在SF_NOTIFY_URL_MAP事件处理过程中,我们可以很方便地获取到host,url,querystring这些信息,
这三个信息也就组成了一个完整的URL。只要我们将host替换成www.yellowrivercharity.com,然后使用ServerSupportFunction向
客户端发送”302 Redirect” URL重定向(重定向到我们新合成的完整URL),这样我们就实现了“域名重写”。
核心代码如下:
PHTTP_FILTER_URL_MAP pMapInfo)
{
CString csNewFullUrl; // 新的完整地址
char szHost[256]={0};
CString csHost;
DWORD dwLen=255;
// 取得host
if(pCtxt->GetServerVariable(“HTTP_HOST”,szHost,&dwLen))
{
csHost=szHost;
csHost.MakeLower();
this->ODS(“host=%s\n”,szHost);
// 检查是否为需要重写的域名
if(csHost==this->csOldDomain) //csOldDomain为原域名,从配置文件中读取
{
csNewFullUrl=”Location: “;
csNewFullUrl+=”http://”+this->csNewDomain; //csNewDomain为新域名,从配置文件中读取
// 取得url
this->ODS(“url=%s\n”,pMapInfo->pszURL);
csNewFullUrl+=pMapInfo->pszURL;
char szQueryString[256]={0};
dwLen=255;
// 取得QueryString
if(pCtxt->GetServerVariable(“QUERY_STRING”,szQueryString,&dwLen))
{
if(strlen(szQueryString)>0)
{
this->ODS(“querystring=%s\n”,szQueryString);
csNewFullUrl+=”?”;
csNewFullUrl+=szQueryString;
}
}
this->ODS(“NewFullUrl=%s\n”,csNewFullUrl);
csNewFullUrl+=”\r\n\r\n”;
// URL 重定向
pCtxt->ServerSupportFunction(SF_REQ_SEND_RESPONSE_HEADER,
(LPVOID) “302 Redirect”,
(DWORD *) csNewFullUrl.GetBuffer(0),0);
}
}
else
this->ODS(“获取host信息失败!\n”);
return SF_STATUS_REQ_NEXT_NOTIFICATION;
}
通过上面三步设置,我们现在就可以通过“http://test.soupkitchen.cn/子目录/子页面””
访问到“www.yellowrivercharity.com/子目录/子页面”了。这样就实现了完整的URL转发。