前段时间我市教育城域网网络结构调整,分给每校一个公网IP地址(网段:211.86.85.0),用于各校网站对外信息发布,要求每校至少配备两台专用服务器。由于学校资金紧张,Web服务器只能由一台普通的教师机来承担,不能满足学校对外网站24小时开放的要求。鉴于此,笔者曾利用“486做路由器”这一技术对学校网络结构进行过改造(详见《中国电脑教育报》2004年第43期G4版《也谈“486做路由器”在校园网中的应用》)。最近,笔者发现利用“网卡绑定多IP地址”这一简单技巧,可以将网络结构更为简化。下面谈谈操作过程及遇到的问题。

  一、改造前网络结构

  改造前学校网络结构如图1所示,其中网关服务器操作系统为Windows 2000 Server,配置成网络路由器,且添加两条静态路由(图2)。

  二、改造后网络结构

  网络结构改造思路:利用Windows 2000 Server中同一块网卡可以绑定多个IP地址这一原理,将公网IP地址211.86.85.244绑定到内网卡上,用网关服务器兼做Web服务器,从而简化网络结构。设置方法:选择“网上邻居→属性→内网卡→属性→“Internet协议(TCP/IP)→高级”,在“IP设置”选项卡中单击[添加],键入公网IP地址211.86.85.244,子网掩码255.255.255.248(图3)。简化后网络结构如图4所示。

  三、修改路由表

  网络结构改变后,在校园网内任一台电脑上均能正常访问Internet,但无法访问区教委网站(211.86.85.242)。经分析可能与网关服务器的路由表有关,于是进入命令行方式,输入“Route print”并回车(图5)。通过图5中矩形框中的一行可以看出,当网关服务器接收到IP为211.86.85.240~211.86.85.247的URL请求时,网关服务器会按照这条路由规则将其发送给指定的网关10.53.84.1——也就是在校园网内寻找211.86.85.240这个网段的地址,而不能正确地路由到默认网关172.18.15.29,从而造成无法访问。弄清楚这点就好办了,只需添加一条静态路由,将其URL请求指向默认网关即可。方法是在命令提示符下输入:

  route -p add 211.86.85.242 mask 255.255.255.255 172.18.15.29

  如果要访问211.86.85.240这个网段内其他的IP地址,同样可以按上述命令添加静态路由。

  四、安全问题

  网络结构改造前,网关服务器还同时兼做文件服务器,对内网用户开放共享,在内网卡绑定公网IP后,这些共享资源有可能暴露于Internet上,由此带来一些安全隐患。因此文件服务器要用另外一台教师机承担,并且将网关服务器的无关用户删除,增加用户密码的复杂度,避免在这些细小之处给非法侵入者可乘之机。

  (山东省莱州市三山岛街道过西小学 赵杰 赵秉玉)

Apache的mod_rewrite是提供了强大URL操作的杀手级的模块,可以实现几乎所有你梦想的URL操作类型,其代价是你必须接受其复杂性,因为mod_rewrite的主要障碍就是初学者不容易理解和运用,即使是Apache专家有时也会发掘出mod_rewrite的新用途。

换句话说:对mod_rewrite,或者是打退堂鼓永不再用,或者是喜欢它并一生受用。

ReWrite可以应用在以下方面或者解决以下问题:
URL的规划
规范的URL
说明:
在有些网站服务器上,一个资源会拥有多个URL,在实际应用和发布中应该被使用的是规范的URL,其他的则是简写或者是内部使用的。无论用户在请求中使用什么形式的URL,他最终看见的都应该是规范的URL。

方案:
对所有的不规范的URL执行一个外部的HTTP重定向,以改变它在浏览器地址栏中的显示及其后继的请求。下例中的规则集用规范的/u/user替换/~user,并修正了/u/user所遗漏的后缀的斜杠。



代码:
RewriteRule ^/~([^/]+)/?(.*) /u/$1/$2 [R]
RewriteRule ^/([uge])/([^/]+)$ /$1/$2/ [R]


规范的主机名
说明:
...
方案:
代码:
RewriteCond %{HTTP_HOST} !^fully\.qualified\.domain\.name [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteCond %{SERVER_PORT} !^80$
RewriteRule ^/(.*) http://fully.qualified.domain.name:%{SERVER_PORT}/$1 [L,R]
RewriteCond %{HTTP_HOST} !^fully\.qualified\.domain\.name [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteRule ^/(.*) http://fully.qualified.domain.name/$1 [L,R]


被移动过的DocumentRoot
说明:
通常,网站服务器的DocumentRoot直接对应于URL"/",但是,它常常不是处于最高一级,而可能只是众多数据池中的一个实体。比如,在Intranet站点中,有/e/www/(WWW的主页)、/e/sww/ (Intranet的主页)等等,而DocumentRoot指向了/e/www/,则必须保证此数据池中的所有内嵌的图片和其他元素对后继请求有效。

方案:
只须重定向URL /到/e/www/即可。这个方案看起来很简单,但只是有了mod_rewrite模块的支持,它才简单,因为传统的URL Aliases机制(由mod_alias及其相关模块提供)只是作了一个前缀匹配,DocumentRoot是一个对所有URL的前缀,因而无法实现这样的重定向。而用mod_rewrite的确很简单:

代码:
RewriteEngine on
RewriteRule ^/$ /e/www/ [R]


后缀斜杠的问题
说明:
每个网管对引用目录后缀斜杠的问题都有一本苦经,如果遗漏了,服务器会产生一个错误,因为如果请求是/~quux/foo而不是/~quux/foo/,服务器会去找一个叫foo的文件,而它是一个目录,所以就报错了。事实上,大多数情况下,它自己会试图修正这个错误,但是有时候需要你手工纠正,比如,在重写了许多CGI脚本中的复杂的URL以后。

方案:
解决这个微妙问题的方案是让服务器自动添加后缀的斜杠。对此,必须使用一个外部的重定向,使浏览器正确地处理后继的对诸如图片的请求。如果仅仅作一个内部的重写,可能只对目录页面有效,而对内嵌有使用相对URL的图片的页面则无效,因为浏览器有请求内嵌目标的可能。比如,如果不用外部重定向,/~quux/foo/index.html页面中对image.gif的请求,其结果将是/~quux/image.gif!。

所以,应该这样写:

代码:
RewriteEngine on
RewriteBase /~quux/
RewriteRule ^foo$ foo/ [R]

又懒又疯狂的做法是把这些写入其宿主目录中的顶级.htaccess中,但是须注意,如此会带来一些处理上的开销。

代码:
RewriteEngine on
RewriteBase /~quux/
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+[^/])$ $1/ [R]


集群网站的同类URL规划
说明:
我们希望在一个Intranet集群网站中,对所有WWW服务器建立一个同类的一致性的URL规划,也就是,所有的URL(对单个服务器来说,是本地的依赖于此服务器的!)是独立于服务器的!我们需要的是一个具有独立于服务器的一致性规划的WWW名称空间,即,URL不需要包含正确的物理的目标服务器,而由集群本身来自动定位物理的目标主机。

方案:
首先,目标服务器的信息来自(产生)于包含有用户、组以及实体的外部地图,其格式形如:

代码:
user1 server_of_user1
user2 server_of_user2
: :


这些信息被存入map.xxx-to-host文件。其次,如果URL在一个服务器上无效,需要引导所有的服务器重定向URL

代码:
/u/user/anypath
/g/group/anypath
/e/entity/anypath



代码:
http://physical-host/u/user/anypath
http://physical-host/g/group/anypath
http://physical-host/e/entity/anypath


以下规则集依靠地图文件来完成这个操作(假定,如果一个用户在地图中没有对应的项,则使用server0为默认服务器):

代码:
RewriteEngine on

RewriteMap user-to-host txt:/path/to/map.user-to-host
RewriteMap group-to-host txt:/path/to/map.group-to-host
RewriteMap entity-to-host txt:/path/to/map.entity-to-host

RewriteRule ^/u/([^/]+)/?(.*) http://${user-to-host:$1|server0}/u/$1/$2
RewriteRule ^/g/([^/]+)/?(.*) http://${group-to-host:$1|server0}/g/$1/$2
RewriteRule ^/e/([^/]+)/?(.*) http://${entity-to-host:$1|server0}/e/$1/$2

RewriteRule ^/([uge])/([^/]+)/?$ /$1/$2/.www/
RewriteRule ^/([uge])/([^/]+)/([^.]+.+) /$1/$2/.www/$3\


移动宿主目录到不同的网站服务器
说明:
通常,许多网管在建立一个新的网站服务器时,都会有这样的要求:重定向一个网站服务器上的所有宿主目录到另一个网站服务器。

方案:
很简单,用mod_rewrite。在老的网站服务器上重定向所有的URL /~user/anypath到http://newserver/~user/anypath。

代码:
RewriteEngine on
RewriteRule ^/~(.+) http://newserver/~$1 [R,L]


结构化的宿主目录
说明:
一些拥有几千个用户的网站通常都使用结构化的宿主目录规划,即,每个宿主目录位于一个带有特定前缀比如其用户名的第一个字符的子目录下。那么,/~foo/anypath代表/home/f/foo/.www/anypath,而/~bar/anypath代表/home/b/bar/.www/anypath。

方案:
可以使用下列规则集来扩展~以达到上述目的。

代码:
RewriteEngine on
RewriteRule ^/~(([a-z])[a-z0-9]+)(.*) /home/$2/$1/.www$3


文件系统的重组
说明:
这是一个不加雕琢的例子:一个大量使用针对目录的规则集以实现平滑观感,而从来不用调整数据结构的杀手级的应用。背景:net.sw从1992年开始,存放了我收集的免费的有效的Unix软件包。它是我的爱好也是我的工作,因为在学习计算机科学的同时,业余时间还做了多年的系统和网络的管理员。每周我都需要整理软件,因而建立了一个层次很深的目录结构来存放各种软件包:

代码:
drwxrwxr-x 2 netsw users 512 Aug 3 18:39 Audio/
drwxrwxr-x 2 netsw users 512 Jul 9 14:37 Benchmark/
drwxrwxr-x 12 netsw users 512 Jul 9 00:34 Crypto/
drwxrwxr-x 5 netsw users 512 Jul 9 00:41 Database/
drwxrwxr-x 4 netsw users 512 Jul 30 19:25 Dicts/
drwxrwxr-x 10 netsw users 512 Jul 9 01:54 Graphic/
drwxrwxr-x 5 netsw users 512 Jul 9 01:58 Hackers/
drwxrwxr-x 8 netsw users 512 Jul 9 03:19 InfoSys/
drwxrwxr-x 3 netsw users 512 Jul 9 03:21 Math/
drwxrwxr-x 3 netsw users 512 Jul 9 03:24 Misc/
drwxrwxr-x 9 netsw users 512 Aug 1 16:33 Network/
drwxrwxr-x 2 netsw users 512 Jul 9 05:53 Office/
drwxrwxr-x 7 netsw users 512 Jul 9 09:24 SoftEng/
drwxrwxr-x 7 netsw users 512 Jul 9 12:17 System/
drwxrwxr-x 12 netsw users 512 Aug 3 20:15 Typesetting/
drwxrwxr-x 10 netsw users 512 Jul 9 14:08 X11/

1996年7月,我决定通过一个漂亮的Web接口公开我的收藏。“漂亮”是指提供一个接口以直接浏览整个目录结构,同时不对这个结构做任何改变 - 甚至也不在结构顶部放置CGI脚本。为什么呢?因为这个结构还要能够被FTP访问,而且我不希望其中有任何Web或者CGI的成分。

方案:
这个方案分为两个部分:第一个部分,是用于在空闲时间建立所有目录页面的CGI脚本集。我把它们放在/e/netsw/.www/,如下:

代码:
-rw-r--r-- 1 netsw users 1318 Aug 1 18:10 .wwwacl
drwxr-xr-x 18 netsw users 512 Aug 5 15:51 DATA/
-rw-rw-rw- 1 netsw users 372982 Aug 5 16:35 LOGFILE
-rw-r--r-- 1 netsw users 659 Aug 4 09:27 TODO
-rw-r--r-- 1 netsw users 5697 Aug 1 18:01 netsw-about.html
-rwxr-xr-x 1 netsw users 579 Aug 2 10:33 netsw-access.pl
-rwxr-xr-x 1 netsw users 1532 Aug 1 17:35 netsw-changes.cgi
-rwxr-xr-x 1 netsw users 2866 Aug 5 14:49 netsw-home.cgi
drwxr-xr-x 2 netsw users 512 Jul 8 23:47 netsw-img/
-rwxr-xr-x 1 netsw users 24050 Aug 5 15:49 netsw-lsdir.cgi
-rwxr-xr-x 1 netsw users 1589 Aug 3 18:43 netsw-search.cgi
-rwxr-xr-x 1 netsw users 1885 Aug 1 17:41 netsw-tree.cgi
-rw-r--r-- 1 netsw users 234 Jul 30 16:35 netsw-unlimit.lst


其中的DATA/子目录包含了上述目录结构,即实在的net.sw,由rdist在需要的时候自动更新。第二个部分的遗留问题是:如何连接这两个结构为一个平滑观感的URL树?我希望在运行适当的CGI脚本而使用各种URL的时候,使用户感觉不到DATA/目录的存在。方案如下:首先,我把下列配置放在服务器上DocumentRoot中的针对目录的配置文件里,以重写公布的URL /net.sw/ 为内部路径 /e/netsw:

代码:
RewriteRule ^net.sw$ net.sw/ [R]
RewriteRule ^net.sw/(.*)$ e/netsw/$1


第一条规则是针对遗漏后缀斜杠的请求的!第二条规则才是真正实现功能的。接着,就是放在针对目录的配置文件/e/netsw/.www/.wwwacl中的杀手级的配置了:

代码:
Options ExecCGI FollowSymLinks Includes MultiViews

RewriteEngine on

# we are reached via /net.sw/ prefix
RewriteBase /net.sw/

# first we rewrite the root dir to
# the handling cgi script
RewriteRule ^$ netsw-home.cgi [L]
RewriteRule ^index\.html$ netsw-home.cgi [L]

# strip out the subdirs when
# the browser requests us from perdir pages
RewriteRule ^.+/(netsw-[^/]+/.+)$ $1 [L]

# and now break the rewriting for local files
RewriteRule ^netsw-home\.cgi.* - [L]
RewriteRule ^netsw-changes\.cgi.* - [L]
RewriteRule ^netsw-search\.cgi.* - [L]
RewriteRule ^netsw-tree\.cgi$ - [L]
RewriteRule ^netsw-about\.html$ - [L]
RewriteRule ^netsw-img/.*$ - [L]

# anything else is a subdir which gets handled
# by another cgi script
RewriteRule !^netsw-lsdir\.cgi.* - [C]
RewriteRule (.*) netsw-lsdir.cgi/$1


阅读提示:

注意前半部分中的标志L(最后),和无对应项('-')
注意后半部分中的符号!(非),和标志C (链)
注意最后一条规则的全匹配模式
代码:
NCSA imagemap和Apache mod_imap
说明:
许多人都希望在从NCSA网站服务器向较现代的Apache网站服务器转移中实现平滑过渡,即希望老的NCSA imagemap程序能在Apache的较现代的mod_imap支持下正常运作。但问题在于,到处都是通过/cgi-bin/imagemap/path/to/page.map引用imagemap程序的连接,而在Apache下,应该写成/path/to/page.map。

方案:
使用全局规则在空闲时间去除所有这些请求的前缀:

代码:
RewriteEngine on
RewriteRule ^/cgi-bin/imagemap(.*) $1 [PT]


在多个目录中搜索页面
说明:
有时会有必要使网站服务器在多个目录中搜索页面,对此,MultiViews或者其他技术无能为力。

方案:
编制一个明确的规则集以搜索目录中的文件。

代码:
RewriteEngine on

# first try to find it in custom/...
# ...and if found stop and be happy:
RewriteCond /your/docroot/dir1/%{REQUEST_FILENAME} -f
RewriteRule ^(.+) /your/docroot/dir1/$1 [L]

# second try to find it in pub/...
# ...and if found stop and be happy:
RewriteCond /your/docroot/dir2/%{REQUEST_FILENAME} -f
RewriteRule ^(.+) /your/docroot/dir2/$1 [L]

# else go on for other Alias or ScriptAlias directives,
# etc.
RewriteRule ^(.+) - [PT]


按照URL的片段设置环境变量
说明:
如果希望保持请求之间的状态信息,但又不希望使用CGI来包装所有页面,而只通过分离URL中的有用信息来编码。

方案:
可以用一个规则集来分离出状态信息,并设置环境变量以备此后用于XSSI或CGI。如此,一个/foo/S=java/bar/的URL会被解析为/foo/bar/,而环境变量STATUS则被设置为"java"。

代码:
RewriteEngine on
RewriteRule ^(.*)/S=([^/]+)/(.*) $1/$3 [E=STATUS:$2]


虚拟用户主机
说明:
如果需要为用户username支持一个www.username.host.domain.com的主页,但不是用在此机器上建虚拟主机的方法,而是用仅在此机器上增加一个DNS记录的方法实现。

方案:
对HTTP/1.0的请求,这是无法实现的;但是对HTTP/1.1的在HTTP头中包含有主机名的请求,可以用以下规则集来内部地重写http://www.username.host.com/anypath为/home/username/anypath:

代码:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.[^.]+\.host\.com$
RewriteRule ^(.+) %{HTTP_HOST}$1 [C]
RewriteRule ^www\.([^.]+)\.host\.com(.*) /home/$1$2


为外来访问者重定向宿主目录
说明:
对不是来自本地域ourdomain.com的外来访问者的请求,重定向其宿主目录URL到另一个网站服务器www.somewhere.com,有时这种做法也会用在虚拟主机的上下文中。

方案:
只须一个重写条件:

代码:
RewriteEngine on
RewriteCond %{REMOTE_HOST} !^.+\.ourdomain\.com$
RewriteRule ^(/~.+) http://www.somewhere.com/$1 [R,L]


重定向失败的URL到其他网站服务器
说明:
如何重写URL以重定向对网站服务器A的失败请求到服务器B,是一个常见的问题。一般,可以用Perl写的CGI脚本通过ErrorDocument来解决,此外,还有mod_rewrite方案。但是须注意,这种方法的执行效率不如用ErrorDocument的CGI脚本!

方案:
第一种方案,有最好的性能而灵活性欠佳,出错概率小所以安全:

代码:
RewriteEngine on
RewriteCond /your/docroot/%{REQUEST_FILENAME} !-f
RewriteRule ^(.+) http://webserverB.dom/$1


但是其问题在于,它只对位于DocumentRoot中的页面有效。虽然可以增加更多的条件(比如同时还处理宿主目录,等等),但是还有一个更好的方法:

代码:
RewriteEngine on
RewriteCond %{REQUEST_URI} !-U
RewriteRule ^(.+) http://webserverB.dom/$1


这种方法使用了mod_rewrite提供的“向前参照(look-ahead)”的功能,是一种对所有URL类型都有效而且安全的方法。但是,对网站服务器的性能会有影响,所以如果网站服务器有一个强大的CPU,那就用这个方法。而在慢速机器上,可以用第一种方法,或者用性能更好的ErrorDocument CGI脚本。

扩展的重定向
说明:
有时候,我们会需要更多的对重定向URL的(有关字符转义机制方面的)控制。通常,Apache内核中的URL转义函数uri_escape()同时还会对anchor转义,即,类似"url#anchor"的URL,因此,你不能用mod_rewrite对此类URL直接重定向。那么如何实现呢?

方案:
必须用NPH-CGI脚本使它自己重定向,因为对NPH(non-parseable headers [无须解析的HTTP头])不会发生转义操作。首先,在针对服务器的配置中(应该位于所有重写规则的最后),引入一种新的URL类型xredirect::

代码:
RewriteRule ^xredirect:(.+) /path/to/nph-xredirect.cgi/$1 \
[T=application/x-httpd-cgi,L]


以强制所有带xredirect:前缀的URL被传送到如下的nph-xredirect.cgi程序:

代码:
#!/path/to/perl
##
## nph-xredirect.cgi -- NPH/CGI script for extended redirects
## Copyright (c) 1997 Ralf S. Engelschall, All Rights Reserved.
##

$| = 1;
$url = $ENV{'PATH_INFO'};

print "HTTP/1.0 302 Moved Temporarily\n";
print "Server: $ENV{'SERVER_SOFTWARE'}\n";
print "Location: $url\n";
print "Content-type: text/html\n";
print "\n";
print "\n";
print "\n";
print "\n";
print "\n";
print "\n";
print "
Moved Temporarily (EXTENDED)
\n";
print "The document has moved here.
\n";
print "\n";
print "\n";

##EOF##


这是一种可以重定向所有URL类型的方法,包括不被mod_rewrite直接支持的类型。所以,还可以这样重定向news:newsgroup:

代码:
RewriteRule ^anyurl xredirect:news:newsgroup


注意:无须对上述规则加[R]或[R,L],因为xredirect:会在稍后被其特殊的传送规则扩展。
文档访问的多路复用
说明:
你知道http://www.perl.com/CPAN的CPAN(Comprehensive Perl Archive Network)吗?它实现了一个重定向以提供,全世界的CPAN镜像中离访问者最近的一个FTP站点,也可以称之为FTP访问多路复用服务。CPAN是通过CGI脚本实现的,那么用mod_rewrite如何实现呢?

方案:
首先,我们注意到mod_rewrite从3.0.0版本开始,还可以重写"ftp:"类型。其次,对客户端顶级域名的路径最近的求取可以用RewriteMap实现。利用链式规则集,并用顶级域名作为查找多路复用地图的键,可以这样做:

代码:
RewriteEngine on
RewriteMap multiplex txt:/path/to/map.cxan
RewriteRule ^/CxAN/(.*) %{REMOTE_HOST}::$1 [C]
RewriteRule ^.+\.([a-zA-Z]+)::(.*)$ ${multiplex:$1|ftp.default.dom}$2 [R,L]

##
## map.cxan -- Multiplexing Map for CxAN
##

de ftp://ftp.cxan.de/CxAN/
uk ftp://ftp.cxan.uk/CxAN/
com ftp://ftp.cxan.com/CxAN/
:
##EOF##

依赖于时间的重写
说明:
在页面内容依时间不同而变化的场合,比如重定向特定页面,许多网管仍然采用CGI脚本的方法,如何用mod_rewrite来实现呢?

方案:
有许多类似TIME_xxx的变量可以用在重写条件中,利用STRING和=STRING的类型比较,并加以连接,就可以实现依赖于时间的重写:

代码:
RewriteEngine on
RewriteCond %{TIME_HOUR}%{TIME_MIN} >0700
RewriteCond %{TIME_HOUR}%{TIME_MIN} <1900
RewriteRule ^foo\.html$ foo.day.html
RewriteRule ^foo\.html$ foo.night.html


此例使URL foo.html在07:00-19:00时指向foo.day.html,而在其余时间,则指向foo.night.html,对主页是一个不错的功能...

对YYYY过渡为XXXX的向前兼容
说明:
在转变了大批.html文件为.phtml,使文档.YYYY过渡成为文档.XXXX后,如何保持URL的向前兼容(仍然虚拟地存在)?

方案:
只须按基准文件名重写,并测试带有新的扩展名的文件是否存在,如果存在,则用新的,否则,仍然用原来的。

代码:
# backward compatibility ruleset for
# rewriting document.html to document.phtml
# when and only when document.phtml exists
# but no longer document.html
RewriteEngine on
RewriteBase /~quux/
# parse out basename, but remember the fact
RewriteRule ^(.*)\.html$ $1 [C,E=WasHTML:yes]
# rewrite to document.phtml if exists
RewriteCond %{REQUEST_FILENAME}.phtml -f
RewriteRule ^(.*)$ $1.phtml [S=1]
# else reverse the previous basename cutout
RewriteCond %{ENV:WasHTML} ^yes$
RewriteRule ^(.*)$ $1.html



内容的处理
新旧URL(内部的)
说明:
假定已经把文件bar.html改名为foo.html,需要对老的URL向前兼容,即让用户仍然可以使用老的URL,而感觉不到文件被改名了。

方案:
通过以下规则内部地重写老的URL为新的:

代码:
RewriteEngine on
RewriteBase /~quux/
RewriteRule ^foo\.html$ bar.html


新旧URL(外部的)
说明:
仍然假定已经把文件bar.html改名为foo.html,需要对老的URL向前兼容,但是要让用户得到文件被改名的暗示,即,其浏览器的地址栏中显示的是新的URL。

方案:
作一个HTTP的强制重定向以改变浏览器和用户界面上的显示:

代码:
RewriteEngine on
RewriteBase /~quux/
RewriteRule ^foo\.html$ bar.html [R]


依赖于浏览器的内容
说明:
至少对重要的顶级页面,有时候有必要提供依赖于浏览器的最佳的内容,即对最新的Netscape提供最大化的版本,对Lynx提供最小化的版本,而对其他的浏览器则提供一个功能一般的版本。

方案:
对此,内容协商无能为力,因为浏览器不提供其那种形式的类型,所以只能在HTTP头"User-Agent"上想办法。以下规则集可以完成这个操作:如果HTTP头"User-Agent"以"Mozilla/3"开头,则页面foo.html被重写为foo.NS.html,而后重写操作终止;如果是"Lynx"或者版本号为1和2的"Mozilla",则重写为foo.20.html;而其他所有的浏览器收到的页面则是foo.32.html:

代码:
RewriteCond %{HTTP_USER_AGENT} ^Mozilla/3.*
RewriteRule ^foo\.html$ foo.NS.html [L]

RewriteCond %{HTTP_USER_AGENT} ^Lynx/.* [OR]
RewriteCond %{HTTP_USER_AGENT} ^Mozilla/[12].*
RewriteRule ^foo\.html$ foo.20.html [L]

RewriteRule ^foo\.html$ foo.32.html [L]



动态镜像
说明:
假定,需要在我们的名称空间里加入其他远程主机的页面。对FTP服务器,可以用mirror程序以在本地机器上维持一个对远程数据的最新的拷贝;对网站服务器,可以用类似的用于HTTP的webcopy程序。但这两种技术都有一个主要的缺点:此本地拷贝必须通过这个程序的执行来更新。所以,比较好的方法是,不采用静态镜像,而采用动态镜像,即,在有数据请求时自动更新(远程主机上更新的数据)。

方案:
为此,使用Proxy Throughput功能(flag [P]),以映射远程页面甚至整个远程网络区域到我们的名称空间:

代码:
RewriteEngine on
RewriteBase /~quux/
RewriteRule ^hotsheet/(.*)$ http://www.tstimpreso.com/hotsheet/$1 [P]

RewriteEngine on
RewriteBase /~quux/
RewriteRule ^usa-news\.html$ http://www.quux-corp.com/news/index.html [P]


反向动态镜像
说明:
...
方案:
代码:
RewriteEngine on
RewriteCond /mirror/of/remotesite/$1 -U
RewriteRule ^http://www\.remotesite\.com/(.*)$ /mirror/of/remotesite/$1


通过Intranet取得丢失的数据
说明:
这是一种在受防火墙保护的(内部的)Intranet(www2.quux-corp.dom)上保存和维护实际数据,而虚拟地运行企业级(外部的)Internet网站服务器(www.quux-corp.dom)的巧妙的方法。这种方法是外部服务器在空闲时间从内部服务器取得被请求的数据。

方案:
首先,必须确保防火墙对内部服务器的保护,并只允许此外部服务器取得数据。对包过滤(packet-filtering)防火墙,可以如下制定防火墙规则:

代码:
ALLOW Host www.quux-corp.dom Port >1024 --> Host www2.quux-corp.dom Port 80
DENY Host * Port * --> Host www2.quux-corp.dom Port 80


按你的实际配置,只要对上例稍作调整即可。接着,建立通过代理后台获取丢失数据的mod_rewrite规则:

代码:
RewriteRule ^/~([^/]+)/?(.*) /home/$1/.www/$2
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/home/([^/]+)/.www/?(.*) http://www2.quux-corp.dom/~$1/pub/$2 [P]


负载的均衡
说明:
如何均衡www.foo.com的负载到www[0-5].foo.com(一共是6个服务器)?

方案:
这个问题有许多可能的解决方案,在此,我们讨论通称为“基于DNS(DNS-based)的”方案,和特殊的使用mod_rewrite的方案:

DNS循环(DNS Round-Robin)
最简单的方法是用BIND的DNS循环特性,只要按惯例设置www[0-9].foo.com的DNS的A(地址)记录,如:

代码:
www0 IN A 1.2.3.1
www1 IN A 1.2.3.2
www2 IN A 1.2.3.3
www3 IN A 1.2.3.4
www4 IN A 1.2.3.5
www5 IN A 1.2.3.6


然后,增加以下各项:

代码:
www IN CNAME www0.foo.com.
IN CNAME www1.foo.com.
IN CNAME www2.foo.com.
IN CNAME www3.foo.com.
IN CNAME www4.foo.com.
IN CNAME www5.foo.com.
IN CNAME www6.foo.com.

注意,上述看起来似乎是错误的,但事实上,它的确是BIND中的一个预期的特性,而且也可以这样用。无论如何,现在www.foo.com已经被解析,BIND可以给出www0-www6 - 虽然每次在次序上会有轻微的置换/循环,客户端的请求可以被分散到各个服务器。可是,这并不是一个优秀的负载均衡方案,因为,DNS解析信息可以被网络中其他名称服务器缓冲,而一旦www.foo.com被解析为wwwN.foo.com,则其后继请求都将被送往www.foo.com。但是最终结果是正确的,因为请求的总量的确被分散到各个服务器了

DNS 负载均衡
一种成熟的基于DNS的负载均衡方法是使用http://www.stanford.edu/~schemers/docs/lbnamed/lbnamed.html的lbnamed程序,它是一个Perl 5程序,带有若干辅助工具,实现了真正的基于DNS的负载均衡。

代理吞吐循环(Proxy Throughput Round-Robin)
这是一个使用mod_rewrite及其代理吞吐特性的方法。首先,在DNS记录中,将www0.foo.com固定为www.foo.com,如下:

代码:
www IN CNAME www0.foo.com.


其次,将www0.foo.com转换为一个专职代理服务器,即,由这个机器把所有到来的URL通过内部代理分散到另外5个服务器(www1-www5)。为此,必须建立一个规则集,对所有URL调用一个负载均衡脚本lb.pl。

代码:
RewriteEngine on
RewriteMap lb prg:/path/to/lb.pl
RewriteRule ^/(.+)$ ${lb:$1} [P,L]


以下是lb.pl:

代码:
#!/path/to/perl
##
## lb.pl -- load balancing script
##

$| = 1;

$name = "www"; # the hostname base
$first = 1; # the first server (not 0 here, because 0 is myself)
$last = 5; # the last server in the round-robin
$domain = "foo.dom"; # the domainname

$cnt = 0;
while () {
$cnt = (($cnt+1) % ($last+1-$first));
$server = sprintf("%s%d.%s", $name, $cnt+$first, $domain);
print "http://$server/$_";
}

##EOF##

最后的说明:这样有用吗?www0.foo.com似乎也会超载呀?答案是:没错,它的确会超载,但是它超载的仅仅是简单的代理吞吐请求!所有诸如SSI、CGI、ePerl等等的处理完全是由其他机器完成的,这个才是要点。
硬件/TCP循环
还有一个硬件解决方案。Cisco有一个叫LocalDirector的东西,实现了TCP/IP层的负载均衡,事实上,它是一个位于网站集群前端的电路级网关。如果你有足够资金而且的确需要高性能的解决方案,那么可以用这个。

反向代理
说明:
...
方案:
代码:
##
## apache-rproxy.conf -- Apache configuration for Reverse Proxy Usage
##

# server type
ServerType standalone
Listen 8000
MinSpareServers 16
StartServers 16
MaxSpareServers 16
MaxClients 16
MaxRequestsPerChild 100

# server operation parameters
KeepAlive on
MaxKeepAliveRequests 100
KeepAliveTimeout 15
Timeout 400
IdentityCheck off
HostnameLookups off

# paths to runtime files
PidFile /path/to/apache-rproxy.pid
LockFile /path/to/apache-rproxy.lock
ErrorLog /path/to/apache-rproxy.elog
CustomLog /path/to/apache-rproxy.dlog "%{%v/%T}t %h -> %{SERVER}e URL: %U"

# unused paths
ServerRoot /tmp
DocumentRoot /tmp
CacheRoot /tmp
RewriteLog /dev/null
TransferLog /dev/null
TypesConfig /dev/null
AccessConfig /dev/null
ResourceConfig /dev/null

# speed up and secure processing

Options -FollowSymLinks -SymLinksIfOwnerMatch
AllowOverride None


# the status page for monitoring the reverse proxy

SetHandler server-status


# enable the URL rewriting engine
RewriteEngine on
RewriteLogLevel 0

# define a rewriting map with value-lists where
# mod_rewrite randomly chooses a particular value
RewriteMap server rnd:/path/to/apache-rproxy.conf-servers

# make sure the status page is handled locally
# and make sure no one uses our proxy except ourself
RewriteRule ^/apache-rproxy-status.* - [L]
RewriteRule ^(http|ftp)://.* - [F]

# now choose the possible servers for particular URL types
RewriteRule ^/(.*\.(cgi|shtml))$ to://${server:dynamic}/$1 [S=1]
RewriteRule ^/(.*)$ to://${server:static}/$1

# and delegate the generated URL by passing it
# through the proxy module
RewriteRule ^to://([^/]+)/(.*) http://$1/$2 [E=SERVER:$1,P,L]

# and make really sure all other stuff is forbidden
# when it should survive the above rules...
RewriteRule .* - [F]

# enable the Proxy module without caching
ProxyRequests on
NoCache *

# setup URL reverse mapping for redirect reponses
ProxyPassReverse / http://www1.foo.dom/
ProxyPassReverse / http://www2.foo.dom/
ProxyPassReverse / http://www3.foo.dom/
ProxyPassReverse / http://www4.foo.dom/
ProxyPassReverse / http://www5.foo.dom/
ProxyPassReverse / http://www6.foo.dom/

##
## apache-rproxy.conf-servers -- Apache/mod_rewrite selection table
##

# list of backend servers which serve static
# pages (HTML files and Images, etc.)
static www1.foo.dom|www2.foo.dom|www3.foo.dom|www4.foo.dom

# list of backend servers which serve dynamically
# generated page (CGI programs or mod_perl scripts)
dynamic www5.foo.dom|www6.foo.dom


新的MIME类型,新的服务
说明:
网上有许多很技巧的CGI程序,但是用法晦涩,许多网管弃之不用。即使是Apache的MEME类型的动作处理器,也仅仅在CGI程序不需要在其输入中包含特殊URL(PATH_INFO和QUERY_STRINGS)时才很好用。首先,配置一种新的后缀为.scgi(for secure CGI)文件类型,其处理器是很常见的cgiwrap程序。问题是:如果使用同类URL规划(见上述),而用户宿主目录中的一个文件的URL是/u/user/foo/bar.scgi,可是cgiwrap要求的URL的格式是/~user/foo/bar.scgi/,以下规则解决了这个问题:

代码:
RewriteRule ^/[uge]/([^/]+)/\.www/(.+)\.scgi(.*) ...
... /internal/cgi/user/cgiwrap/~$1/$2.scgi$3 [NS,T=application/x-http-cgi]


另外,假设需要使用其他程序:wwwlog(显示access.log中的一个URL子树)和wwwidx(对一个URL子树运行Glimpse),则必须对这些程序提供URL区域作为其操作对象。比如,对/u/user/foo/执行swwidx程序的超链是这样的:

代码:
/internal/cgi/user/swwidx?i=/u/user/foo/


其缺点是,必须同时硬编码超链中的区域和CGI的路径,如果重组了这个区域,就需要花费大量时间来修改各个超链。

方案:
方案是用一个特殊的新的URL格式,自动拼装CGI参数:

代码:
RewriteRule ^/([uge])/([^/]+)(/?.*)/\* /internal/cgi/user/wwwidx?i=/$1/$2$3/
RewriteRule ^/([uge])/([^/]+)(/?.*):log /internal/cgi/user/wwwlog?f=/$1/$2$3


现在,这个搜索到/u/user/foo/的超链简化成了:

代码:
HREF="*"


它会被内部地自动转换为

代码:
/internal/cgi/user/wwwidx?i=/u/user/foo/


如此,可以为使用:log的超链,拼装出调用CGI程序的参数。

从静态到动态
说明:
如何无缝转换静态页面foo.html为动态的foo.cgi,而不为浏览器/用户所察觉。

方案:
只须重写此URL为CGI-script,以强制为可以作为CGI-script运行的正确的MIME类型。如此,对/~quux/foo.html的请求其实会执行/~quux/foo.cgi。

代码:
RewriteEngine on
RewriteBase /~quux/
RewriteRule ^foo\.html$ foo.cgi [T=application/x-httpd-cgi]


空闲时间内的内容协商
说明:
这是一个很难解的功能:动态生成的静态页面,即,它应该作为静态页面发送(从文件系统中读出,然后直接发出去),但是如果它丢失了,则由服务器动态生成。如此,可以静态地提供CGI生成的页面,除非有人(或者是一个cronjob)删除了这些静态页面,而且其内容可以得到更新。

方案:
以下规则集实现这个功能:
代码:
RewriteCond %{REQUEST_FILENAME} !-s
RewriteRule ^page\.html$ page.cgi [T=application/x-httpd-cgi,L]
这样,如果page.html不存在或者文件大小为null,则对page.html的请求会导致page.cgi的运行。其中奥妙在于,page.cgi是一个将输出写入page.html的(同时也写入STDOUT)的常规的CGI脚本,执行完毕,服务器则将page.html的内容发出。如果网管需要强制更新其内容,只须删除page.html即可(通常由一个cronjob完成)。

自动更新的文档
说明:
建立一个复杂的页面,能够在用编辑器写了一个更新的版本时自动在浏览器上得到刷新,这不是很好吗?这可能吗?

方案:
这是可行的! 这需要综合利用MIME多成分、网站服务器的NPH和mod_rewrite的URL操控特性。首先,建立一个新的URL特性:对在文件系统中更新时需要刷新的所有URL加上:refresh。

代码:
RewriteRule ^(/[uge]/[^/]+/?.*):refresh /internal/cgi/apache/nph-refresh?f=$1


然后,修改URL

代码:
/u/foo/bar/page.html:refresh


以内部地操控此URL

代码:
/internal/cgi/apache/nph-refresh?f=/u/foo/bar/page.html


接着就是NPH-CGI脚本部分了。虽然,人们常说"left as an exercise to the reader",我还是给出答案了。

代码:
#!/sw/bin/perl
##
## nph-refresh -- NPH/CGI script for auto refreshing pages
## Copyright (c) 1997 Ralf S. Engelschall, All Rights Reserved.
##
$| = 1;

# split the QUERY_STRING variable
@pairs = split(/&/, $ENV{'QUERY_STRING'});
foreach $pair (@pairs) {
($name, $value) = split(/=/, $pair);
$name =~ tr/A-Z/a-z/;
$name = 'QS_' . $name;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
eval "\$$name = \"$value\"";
}
$QS_s = 1 if ($QS_s eq '');
$QS_n = 3600 if ($QS_n eq '');
if ($QS_f eq '') {
print "HTTP/1.0 200 OK\n";
print "Content-type: text/html\n\n";
print "&b&ERROR&/b&: No file given\n";
exit(0);
}
if (! -f $QS_f) {
print "HTTP/1.0 200 OK\n";
print "Content-type: text/html\n\n";
print "&b&ERROR&/b&: File $QS_f not found\n";
exit(0);
}

sub print_http_headers_multipart_begin {
print "HTTP/1.0 200 OK\n";
$bound = "ThisRandomString12345";
print "Content-type: multipart/x-mixed-replace;boundary=$bound\n";
&print_http_headers_multipart_next;
}

sub print_http_headers_multipart_next {
print "\n--$bound\n";
}

sub print_http_headers_multipart_end {
print "\n--$bound--\n";
}

sub displayhtml {
local($buffer) = @_;
$len = length($buffer);
print "Content-type: text/html\n";
print "Content-length: $len\n\n";
print $buffer;
}

sub readfile {
local($file) = @_;
local(*FP, $size, $buffer, $bytes);
($x, $x, $x, $x, $x, $x, $x, $size) = stat($file);
$size = sprintf("%d", $size);
open(FP, "&$file");
$bytes = sysread(FP, $buffer, $size);
close(FP);
return $buffer;
}

$buffer = &readfile($QS_f);
&print_http_headers_multipart_begin;
&displayhtml($buffer);

sub mystat {
local($file) = $_[0];
local($time);

($x, $x, $x, $x, $x, $x, $x, $x, $x, $mtime) = stat($file);
return $mtime;
}

$mtimeL = &mystat($QS_f);
$mtime = $mtime;
for ($n = 0; $n & $QS_n; $n++) {
while (1) {
$mtime = &mystat($QS_f);
if ($mtime ne $mtimeL) {
$mtimeL = $mtime;
sleep(2);
$buffer = &readfile($QS_f);
&print_http_headers_multipart_next;
&displayhtml($buffer);
sleep(5);
$mtimeL = &mystat($QS_f);
last;
}
sleep($QS_s);
}
}

&print_http_headers_multipart_end;

exit(0);

##EOF##
大型虚拟主机
说明:
Apache的功能很强,在有几十个虚拟主机的情况下运行得很好,但是如果你是ISP,需要提供几百个虚拟主机,那么这就不是一个最佳的选择了。

方案:
为此,需要用代理吞吐(Proxy Throughput)功能(flag [P])映射远程页面甚至整个远程网络区域到自己的名称空间:

代码:
##
## vhost.map
##
www.vhost1.dom:80 /path/to/docroot/vhost1
www.vhost2.dom:80 /path/to/docroot/vhost2
:
www.vhostN.dom:80 /path/to/docroot/vhostN

代码:
##
## httpd.conf
##
:
# use the canonical hostname on redirects, etc.
UseCanonicalName on

:
# add the virtual host in front of the CLF-format
CustomLog /path/to/access_log "%{VHOST}e %h %l %u %t \"%r\" %>s %b"
:

# enable the rewriting engine in the main server
RewriteEngine on

# define two maps: one for fixing the URL and one which defines
# the available virtual hosts with their corresponding
# DocumentRoot.
RewriteMap lowercase int:tolower
RewriteMap vhost txt:/path/to/vhost.map

# Now do the actual virtual host mapping
# via a huge and complicated single rule:
#
# 1. make sure we don't map for common locations
RewriteCond %{REQUEST_URL} !^/commonurl1/.*
RewriteCond %{REQUEST_URL} !^/commonurl2/.*
:
RewriteCond %{REQUEST_URL} !^/commonurlN/.*
#
# 2. make sure we have a Host header, because
# currently our approach only supports
# virtual hosting through this header
RewriteCond %{HTTP_HOST} !^$
#
# 3. lowercase the hostname
RewriteCond ${lowercase:%{HTTP_HOST}|NONE} ^(.+)$
#
# 4. lookup this hostname in vhost.map and
# remember it only when it is a path
# (and not "NONE" from above)
RewriteCond ${vhost:%1} ^(/.*)$
#
# 5. finally we can map the URL to its docroot location
# and remember the virtual host for logging puposes
RewriteRule ^/(.*)$ %1/$1 [E=VHOST:${lowercase:%{HTTP_HOST}}]
:


对访问的限制
阻止Robots
说明:
如何阻止一个完全匿名的robot取得特定网络区域的页面?一个/robots.txt文件可以包含若干"Robot Exclusion Protocol(robot排除协议)"的行,但不足以阻止此类robot。

方案:
可以用一个规则集以拒绝对网络区域/~quux/foo/arc/(对一个很深的目录区域进行列表可能会使服务器产生很大的负载)的访问。还必须确保仅阻止特定的robot,就是说,仅仅阻止robot访问主机是不够的,这样会同时也阻止了用户访问该主机。为此,就需要对HTTP头的User-Agent信息作匹配。

代码:
RewriteCond %{HTTP_USER_AGENT} ^NameOfBadRobot.*
RewriteCond %{REMOTE_ADDR} ^123\.45\.67\.[8-9]$
RewriteRule ^/~quux/foo/arc/.+ - [F]
阻止内嵌的图片
说明:
假设,http://www.quux-corp.de/~quux/有一些内嵌图片的页面,这些图片很好,所以就有人用超链连到他们自己的页面中了。由于这样徒然增加了我们的服务器的流量,因此,我们不愿意这种事情发生。

方案:
虽然,我们不能100%地保护这些图片不被写入别人的页面,但至少可以对发出HTTP Referer头的浏览器加以限制。

代码:
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://www.quux-corp.de/~quux/.*$ [NC]
RewriteRule .*\.gif$ - [F]

RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !.*/foo-with-gif\.html$
RewriteRule ^inlined-in-foo\.gif$ - [F]


对主机的拒绝
说明:
如何拒绝一批外部列表中的主机对我们服务器的使用?

方案:
代码:
For Apache >= 1.3b6:

RewriteEngine on
RewriteMap hosts-deny txt:/path/to/hosts.deny
RewriteCond ${hosts-deny:%{REMOTE_HOST}|NOT-FOUND} !=NOT-FOUND [OR]
RewriteCond ${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND} !=NOT-FOUND
RewriteRule ^/.* - [F]

For Apache <= 1.3b6:

RewriteEngine on
RewriteMap hosts-deny txt:/path/to/hosts.deny
RewriteRule ^/(.*)$ ${hosts-deny:%{REMOTE_HOST}|NOT-FOUND}/$1
RewriteRule !^NOT-FOUND/.* - [F]
RewriteRule ^NOT-FOUND/(.*)$ ${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND}/$1
RewriteRule !^NOT-FOUND/.* - [F]
RewriteRule ^NOT-FOUND/(.*)$ /$1

代码:
##
## hosts.deny
##
## ATTENTION! This is a map, not a list, even when we treat it as such.
## mod_rewrite parses it for key/value pairs, so at least a
## dummy value "-" must be present for each entry.
##

193.102.180.41 -
bsdti1.sdm.de -
192.76.162.40 -

对代理的拒绝
说明:
如何拒绝某个主机或者来自特定主机的用户使用Apache代理?

方案:
首先,要确保Apache网站服务器在编译时配置文件中mod_rewrite在mod_proxy的下面(!),使它在mod_proxy之前被调用。然后,如下拒绝某个主机...

代码:
RewriteCond %{REMOTE_HOST} ^badhost\.mydomain\.com$
RewriteRule !^http://[^/.]\.mydomain.com.* - [F]

...如下拒绝user@host-dependent:

代码:
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} ^badguy@badhost\.mydomain\.com$
RewriteRule !^http://[^/.]\.mydomain.com.* - [F]


特殊的认证
说明:
有时候,会需要一种非常特殊的认证,即,对一组明确指定的用户,允许其访问,而没有(在使用mod_access的基本认证方法时可能会出现的)任何提示。

方案:
可是使用一个重写条件列表来排除所有的朋友:

代码:
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend1@client1.quux-corp\.com$
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend2@client2.quux-corp\.com$
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend3@client3.quux-corp\.com$
RewriteRule ^/~quux/only-for-friends/ - [F]


基于提交者(Referer)的反射器
说明:
如何配置一个基于HTTP头"Referer"的反射器以反射到任意数量的提交页面?

方案:
使用这个很技巧的规则集...

代码:
RewriteMap deflector txt:/path/to/deflector.map

RewriteCond %{HTTP_REFERER} !=""
RewriteCond ${deflector:%{HTTP_REFERER}} ^-$
RewriteRule ^.* %{HTTP_REFERER} [R,L]

RewriteCond %{HTTP_REFERER} !=""
RewriteCond ${deflector:%{HTTP_REFERER}|NOT-FOUND} !=NOT-FOUND
RewriteRule ^.* ${deflector:%{HTTP_REFERER}} [R,L]


... 并结合对应的重写地图:

代码:
##
## deflector.map
##

http://www.badguys.com/bad/index.html -
http://www.badguys.com/bad/index2.html -
http://www.badguys.com/bad/index3.html http://somewhere.com/

它可以自动将请求(在地图中指定了"-"值的时候)反射回其提交页面,或者(在地图中URL有第二个参数时)反射到一个特定的URL。


其他
外部重写引擎
说明:
一个常见的问题: 如何解决似乎无法用mod_rewrite解决的FOO/BAR/QUUX/之类的问题?

方案:
可以使用一个与RewriteMap功能相同的外部RewriteMap程序,一旦它在Apache启动时被执行,则从STDIN接收被请求的URL,并将处理过(通常是重写过的)的URL(以相同顺序!)在STDOUT输出。

代码:
RewriteEngine on
RewriteMap quux-map prg:/path/to/map.quux.pl
RewriteRule ^/~quux/(.*)$ /~quux/${quux-map:$1}


代码:
#!/path/to/perl

# disable buffered I/O which would lead
# to deadloops for the Apache server
$| = 1;

# read URLs one per line from stdin and
# generate substitution URL on stdout
while (<>) {
s|^foo/|bar/|;
print $_;
}

这是一个作演示的例子,只是把所有的URL /~quux/foo/...重写为/~quux/bar/...,而事实上,可以把它修改以获得任何你需要的功能。但是要注意,虽然一般用户都可以使用,可是只有系统管理员才可以定义这样的地图。

[ 2005/03/15 00:33 | by 网络毛毛虫 ]
收购新浪还需要宣布什么?做的事情我们已经宣布了。今后会怎么样,要等到我们认为可以的时候,就好像谈对象结婚一样。

最近你打开新浪的首页,会发现安装IGAME的对话框会自动弹出,IGAME是什么,是互动类的网络游戏,把新浪改成互动娱乐的不是盛大,说新浪有多纯洁是假的。

盛大收购新浪的过程不是谁妥协谁的问题,新浪的价值只有盛大最认可。“我把我所有的现金砸进去,而且是按照市场价买入的,冒这么大风险。全中国最爱新浪的是我。”


———陈天桥
[ 2005/03/14 20:34 | by 网络毛毛虫 ]

听过西洋情人节,也听过七夕情人节。那么你知道什么是“白色情人节”吗? 其实,“情人节”与“白色情人节”最早起源于三世纪时的罗马。罗马皇帝在2月14日救了一对因为原本因违反恋爱结婚禁令而要被处死的恋人,罗马皇帝为了纪念这一天而设立了情人节。而在一个月后的3月14日,这对获救的恋人宣誓恋情将至死不渝,为纪念这天于是另订为白色情人节。而此节日就从欧洲开始流传到世界其它地方。

   而在日本的民间传说中,2月14日原本是女孩子对男孩子诉诸情意的日子,由女孩子送情人礼物给男孩子但是渐渐发展到最後,已经不分彼此,现在的情人节由谁主动送礼物已经不重要了。

   现在,“白色情人节”在日本、台湾等地已非常流行。在日本,如果一方在2月14日当天收到异性送的情人礼表达爱意,而且对对方也有同样的好感或情意时,就会在3月14日回送对方一份情人礼物,那表示今年,彼此已经心心相印了。   如果你也收到一份期待的情人礼物,那何妨趁著“白色情人节”这一天让对方也感受到你的爱意呢?



二楼:这样改


三楼:晕,黑漆漆的,这样才好看


四楼:不要那个MM是吧,这样满意吗


五楼:小菜一碟!


六楼:俺是厚道人


七楼:don’t forget!世上还是有好人的



八楼:留念就要这样


九楼:楼上的还不够多,至少要摆个葫芦兄弟的造型


十楼:怀旧的都来看看什么叫葫芦兄弟


十一楼:不能比啊


十二楼:哈哈,来个限制级的



十三楼:限制级是这样的
 

[ 2005/03/06 20:43 | by 网络毛毛虫 ]

党校培训的名额这次掉到我头上了。今天晚上把名单输入计算机了。

距离真正的入党还有很长的距离。不管入党是好是坏。但是我觉得,加入比不加入好。多一个名号比很多要强。

所以这方面我还是争取去加入。

[ 2005/03/06 13:47 | by 网络毛毛虫 ]

收集的几个瑞星2005、江民杀毒软件增量升级的网站。盗版用户可以升级!

http://www.zrit.com/rising

http://www.abcbit.com/rising

http://www.cnxhacker.com/rav

http://www.fuwu.net.cn/rising/rising.htm

一、有关CN域名交易涉及的名词解释

  1. 域名注册管理机构:中国互联网络信息中心,承担顶级域名系统的运行、维护和管理工作。

  2. 域名交易管理机构:指的是中国互联网络信息中心,其职责是负责运行和管理域名交易系统,维护域名交易中央数据库,认证域名交易服务机构提供域名交易服务;

  3. 域名交易服务机构:是经域名注册管理机构认证从事域名交易服务的机构;

  4. 域名注册服务机构:是指受理域名注册申请,直接完成域名在国内顶级域名数据库中注册的机构。

  5. 域名交易者:是依照本规则进行域名交易的人,包括卖方与买方。

  6. 域名交易状态查询:

  (1) 不可交易:在此状态下,域名无法交易,域名默认的状态或域名注册完毕后即为该状态;

  (2) 正常:当卖方通过中国互联网络信息中心的网站设置域名为可交易后,域名状态改为“正常”,在此状态下可以进行域名交易;

  (3) 交易等待验证:域名交易服务机构确认卖方提供信息,登录中国互联网络信息中心网站确认交易后,域名状态改为“交易等待验证”;

  (4) 交易进行中:卖方通过Email和域名密码确认交易,验证通过后,域名状态由“交易等待验证”转为“交易进行中”,此时域名被锁定。

  (5) 交易确认中:买方、卖方及交易服务机构三方签署交易协议,交易服务机构确认交易完成,域名状态由“交易进行中”转为“交易确认中”。

  7. 域名密码:也就是域名管理密码,是域名注册时自动生成域名密码,卖方可与注册服务机构进行联系索要。此密码同域名转移密码

  8. 域名过户:由域名注册服务机构在验证域名交易码后进行域名过户操作。

  二、域名交易的卖方流程

  1. 卖方通过域名和域名密码到中国互联网络信息中心网站进行域名状态更改,域名状态由“不可交易”转为“正常”后,域名便可进行交易。域名状态查询见:

  2. 卖方选择域名交易管理机构中国互联网络信息中心认证的域名交易服务机构进行域名交易。

  3. 卖方可以通过交易服务机构网站、或提交书面、email、传真提出域名交易申请,在提交申请时需同时接受交易服务机构制订的相关交易条款。

  4. 卖方及买方提交资料,交易服务机构对卖方和买方身份、交易域名的有效性及交易时间的有效性进行验证,符合规定可以进行交易。

  5. 域名交易服务机构在中国互联网络信息中心提供的链接请求交易,请求交易后系统将此域名状态由“正常”转为“交易等待验证”状态。在“交易等待验证”状态下,域名注册人的信息可以更改 ,但其他交易服务机构不能再对该域名提交交易申请。

  6. 域名交易服务机构请求交易后,中国互联网络信息中心开始进行域名审核,在此次交易过程中,如遇到违反相关规定域名正在进行交易,中国互联网络信息中心均可取消该域名的交易权利,强制撤销该域名正在进行的交易,并将该域名加入到域名禁止交易库中;域名状态由“交易等待验证”转为“正常”。

  7. 交易服务机构发出交易请求后,交易系统通过email形式给卖方发送密码验证邮件。

  8. 卖方通过Email里提供的链接和域名密码进行交易验证,验证通过后,域名状态由“交易等待验证”转为“交易进行中”,此时域名被锁定。

  若卖方因各种原因没有确认交易,14日之内交易超时,域名状态转为“正常”,卖方可重新申请进行交易,也可将域名从可交易列表中删除。

  9. 交易系统通过接口给交易服务机构发送域名已激活的通知。

  10. 买方登陆交易服务机构网站,寻找合适域名,同意交易服务机构所规定协议,即可进行域名交易。

  11. 交易服务机构确认后,进行交易撮合,买卖双方按照交易服务机构制订的交易流程进行议价。

  若三方对交易议价失败,域名交易服务机构取消交易,域名状态由“交易进行中”转为“正常”。此次交易终止,卖方可重新开始交易流程。

  交易撮合成功议价在有效时间范围内完成的,有效交易的时间范围为域名注册后的15日后到域名到期前15日前,即域名交易服务机构发出请求交易开始时间必须在域名注册后的15日后,域名交易结束时间必须在域名到期日前15日。

  12. 买方、卖方及交易服务机构三方签署交易协议,交易服务机构确认交易完成,填写买方信息,域名状态由“交易进行中”转为“交易确认中”。

  13. 域名交易服务机构确认交易完成后,可通过域名交易系统查询到域名交易码。

  14. 卖方提供域名过户资料给域名注册服务机构。

  按照域名注册服务机构的要求提交用以确认卖方变更注册人信息的必要审核材料(例如身份证、企业营业执照等)

  15. 域名交易服务机构将交易码发给卖方域名所在的注册服务机构。

  16. 注册服务机构在15日内登录到中国互联网络信息中心的域名交易系统上进行域名交易码的确认。

  17. 注册服务机构验证交易码完成后,域名状态由“交易确认中”转为“不可交易”,域名锁定解除。

  18. 注册服务机构更改域名密码,并修改相关注册人信息。注册服务机构以其规定的方式将密码通知买方。

  19过户完成,交易完毕。

  附交易流程图

  三、有关域名交易的申请与处理

  1. 适用于本域名交易的域名类型是什么?

  由中国互联网络信息中心负责注册管理,并提供解析服务的互联网络域名;

  2. 什么样的域名不可以进行域名交易?

  以gov.cn、edu.cn结尾及被禁止注册和限制注册的域名不能交易。

  3. 哪些类型的域名不能申请交易?

  a) 反对宪法所确定的基本原则的;

  b) 危害国家安全,泄露国家秘密,颠覆国家政权,破坏国家统一的;

  c) 损害国家荣誉和利益的;

  d) 煽动民族仇恨、民族歧视,破坏民族团结的;

  e) 破坏国家宗教政策,宣扬邪教和封建迷信的;

  f) 散布谣言,扰乱社会秩序,破坏社会稳定的;

  g) 散布淫秽、色情、赌博、暴力、凶杀、恐怖或者教唆犯罪的;

  h) 侮辱或者诽谤他人,侵害他人合法权益的;

  含有法律、行政法规禁止的其他内容的。

  4. 到哪里提出域名交易申请?

  可以到中国互联网络信息中心认证的域名交易服务机构提出申请。 例如:www.dnsdna.cn

  5 .申请域名交易卖方需要哪些材料?

  需要提交证明卖方为域名所有人的材料,具体材料以域名交易机构和注册服务机构的要求为准。

  6. 域名的密码怎样获得?

  每个注册服务机构的管理方式不同,域名密码可直接与注册服务机构联系。

  7. 域名交易的有效时间是什么?

  域名有效交易的时间范围为域名注册后的15日后到域名到期前15日前,即域名交易服务机构发出请求交易开始时间必须在域名注册后的15日后,域名交易结束时间必须在域名到期日前15日。

  8. 是否可以查询到域名交易情况?

  可以登录cnnic网站域名交易whois进行查询。同时,域名所有者可以通过我们的查询页面,输入域名和密码查询交易的详细信息。

  具体的见交易状态说明见名词解释。

  9. 交易完成后,多长时间可以过户成功?

  经注册服务机构验证成功后,注册服务机构应于15日内完成更改域名密码和修改相关注册人信息。

  10. 域名交易结束后,多长时间就能进行下次交易?

  只要域名状态为“正常”,就能进行下次交易,但要保证域名在有效交易时间内。

  11.域名密码与域名转移密码有什么区别?

  与域名交易密码相同。

  四、有关域名交易的更改及撤消

  12.是否可以撤销域名交易?

  可以在域名注册管理机构确认域名交易码之前,卖方均可与域名交易机构联系进行撤销。

  13.如果审核不通过后,交易如何再继续?

  如果审核不通过后,交易即被取消,不能继续交易。

  14.卖方没有确认域名交易,多长时间交易取消?

  若卖方因各种原因没有确认交易,14日之内交易超时,域名状态转为“正常”。

  五、交易费用的结转

  域名交易费用结算按照买卖双方和域名交易服务机构之间签订的三方协议为准。除此之外,在域名过户成功后,买方需要向域名注册服务机构缴纳一年域名费用 ,即续费一年。

  六、交易中涉及的其他问题

  15.没有收到系统发来的交易密码确认邮件怎么办?

  可以与域名交易管理机构联系,传真加盖卖方公章的申请补发交易密码确认邮件的申请。

  16.域名是否可以通过不同的域名交易机构申请交易?

  当域名交易机构发出交易请求后,其他交易服务机构不能再对该域名提交交易申请。

  17.交易过程中是否可以对域名信息进行修改?

  域名状态为“交易等待验证”状态时,域名注册人的信息可以更改;而在交易期间,域名状态变更为“交易进行中”,域名被锁定后,交易的域名信息均不能被修改;

  18.如果对已经交易完毕的域名有异议,如何处理?

  对已经完成的域名交易有异议的,可通过域名争议解决程序或任何法律程序加以解决。

  19.在交易过程中,需要注意以下事项:

  (1) 域名所有权属于卖方;

  (2) 域名状态设置为“正常”状态才能进行交易;

  (3) 提供的域名管理联系人的信息要真实准确,以保证能及时收到邮件;

  20.域名交易的好处

  (1) 培育和发展健康的域名交易市场;

  (2) 规范域名交易行为;

  (3) 促进域名资源的优化配置;

[ 2005/03/05 22:53 | by 网络毛毛虫 ]

这次同步官方升级。有部分模板我在修改中

[ 2005/03/05 22:00 | by 网络毛毛虫 ]
‘我喜欢’ (版本一) http://www.mcdonalds.com.cn/tvc/Brand/brand_2003a.wmv ‘我喜欢’ (版本二) http://www.mcdonalds.com.cn/tvc/Brand/brand_2003b.wmv 求婚 http://www.mcdonalds.com.cn/tvc/Brand/ou_marry_me.wmv 秋千宝 http://www.mcdonalds.com.cn/tvc/Brand/BabySwing.wmv 鬼脸篇 http://www.mcdonalds.com.cn/tvc/Brand/makingfaces.wmv 麦乐鸡 http://www.mcdonalds.com.cn/tvc/Brand/en_McNuggets_15.wmv 麦香鱼 http://www.mcdonalds.com.cn/tvc/Promotion/3_FOF_15.wmv 双层芝士 http://www.mcdonalds.com.cn/tvc/Promotion/Cheeseburger_15.wmv 麦香鸡 http://www.mcdonalds.com.cn/tvc/Promotion/Chicken_15.wmv 麦香猪柳蛋 http://www.mcdonalds.com.cn/tvc/Promotion/usage_Burger_15.wmv 汉堡包 http://www.mcdonalds.com.cn/tvc/Promotion/ger3dollars.wmv 板烧鸡腿汉堡 http://www.mcdonalds.com.cn/tvc/Promotion/scfb.wmv KFC 老北京鸡肉卷-融合篇 http://www.kfc.com.cn/fun/download/tvc/download/22.zip 吃不垮篇 http://www.kfc.com.cn/fun/download/tvc/download/18.zip 龙篇 http://www.kfc.com.cn/fun/download/tvc/download/19.zip 外带全家桶-休闲老妈篇 http://www.kfc.com.cn/fun/download/tvc/download/20.zip 四季鲜蔬精挑细选篇 http://www.kfc.com.cn/fun/download/tvc/download/21.zip 温暖篇 http://www.kfc.com.cn/fun/download/tvc/download/01.zip 秋千篇 http://www.kfc.com.cn/fun/download/tvc/download/02.zip 风扇篇 http://www.kfc.com.cn/fun/download/tvc/download/03.zip 时代洪流篇 http://www.kfc.com.cn/fun/download/tvc/download/04.zip 泰国味道篇 http://www.kfc.com.cn/fun/download/tvc/download/05.zip 不约而同篇 http://www.kfc.com.cn/fun/download/tvc/download/06.zip 聚餐篇 http://www.kfc.com.cn/fun/download/tvc/download/07.zip 摘星篇 http://www.kfc.com.cn/fun/download/tvc/download/08.zip 无所不在篇 http://www.kfc.com.cn/fun/download/tvc/download/09.zip 动画广告 http://www.kfc.com.cn/fun/download/event/wing.zip
 
分页: 27/47 第一页 上页 22 23 24 25 26 27 28 29 30 31 下页 最后页 [ 显示模式: 摘要 | 列表