Apache URL重定向指南

mod_rewrite入门
Apache mod_rewrite模块是一个处理URL而又极为复杂的模块,使用mod_rewrite你可处理所有和URL有关的问题,你所付出的就是花时间去了解mod_rewrite的复杂架构,一般初学者都很难实时理解mod_rewrite的用法,有时Apache专家也要mod_rewrite来发展Apache的新功能。
换句话说,当你成功使用mod_rewrite做到你期望的东西,就不要试图再接触mod_rewrite了,因为mod_rewrite的功能实在过于强大。本章的例子会介绍几个成功的例子给你摸索,不像FAQ形式般把你的问题解答。
实用解决方法
这里还有很多未被发掘的解决方法,请大家耐心地学习如何使用mod_rewrite。

注意: 由于各人的服务器的配置都有所不同,你可能要更改设定来测试以下例子,例如使用mod_alias和mod_userdir时要加上[PT],或者使用.htaccess来重定向而非主设定文件等,请尽量理解各例子如何运作,不要生吞活剥地背诵。

URL规划
正规URL
描述:
在某些网页服务器中,一项资源可能会有数个URL,通常都会公布一正规URL(即真正发放的URL),其它URL都会被视为快捷方式或只供内部使用等,无论用户在使用快捷方式或正规URL,用户最后所重定向到的URL必需为正规。
方法:
我们可将所有非正规的URL重定向至正规的URL中,以下例子把非正规的「 /~user」换成正规的「 /u/user」,并且加上「/」号结尾。.

RewriteRule   ^/~([^/]+)/?(.*)    /u/$1/$2 [R]
RewriteRule   ^/([uge])/([^/]+)___FCKpd___1nbsp;/$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被移动
描述:
URL的「/」通常都会映像到DocumentRoot上,但DocumentRoot有时并非重始就限定在某个目录上,它可能只是一个或多个目录的对照而矣。例如我们的内联网址为 /e/www/ (WWW的主目录)和 /e/sww/ (内联网的主目录)等等,因为所有的网页资料都放在 /e/www/目录内,我们要确定所有内嵌的图像都能正确显示。
方法:
我们只要把「 /」重定向至「 /e/www/」,用mod_rewrite来解决比用mod_alias来解决更为简洁,因为URL 别名只会比较 URL 的前部分,但重定向因可能涉及另一台服务器而需要不同的前缀部分(前缀部分已受DocumentRoot限制),所以mod_rewrite是最好的解决方法::

RewriteEngine on
RewriteRule   ^/$ /e/www/ [R]

结尾斜线问题
描述:
每个网主都曾受到结尾斜线问题的折磨,若在URL中没有结尾斜线,服务器就会认为URL无效并返回错误,因为服务器会根据 /~quux/foo去寻找 foo这个档案,而非显示这个目录。其实很多时候,这问题应留待用户自己加「/」去解决,但有时你也可以完成步骤。例如你做了多次URL重定向,而目的地为一个CGI程序。
方法:
最直观的方法就是令Apache自动加上「/」,使用外部重定向令浏览器能正确找到档案,若我们只做内部重定向,就只能正确显示目录页,在这目录页的图像文件会因相对URL的问题而找不到。例如我们请求 /~quux/foo/index.htmlimage.gif时,重定向后会变成 /~quux/image.gif
所以我们应使用以下方法:

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

这方法也适用于.htaccess文件在各目录内设定,但这设定会覆盖原先主配置文件。

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

利用均一的URL版面规划网络群组
描述:
所有的网页服务器都有相同的URL版面,即无论用户向哪个主机发出请求URL,用户都会接收到相同的网页,使URL独立于服务器本身。我们的目的在于如何在Apache服务器不能响应时,都能有一个常规(而又独立于服务器运作)的网页传送给用户,设立网络群组可将这网页送至远程。
方法:
首先,服务器需要一外部文件把网站的用户、用户组及其它资料存储,这文件的格式如下
user1 server_of_user1
user2 server_of_user2
:      :
把以上资料存入 map.xxx-to-host。然后指示服务器把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
当服务器接收到不正确的URL时,服务器会跟随以下指示把URL映像到特定的档案(若URL并没有相对应的记录,就会重定向至 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])/([^/]+)/?___FCKpd___37nbsp;         /$1/$2/.www/
RewriteRule   ^/([uge])/([^/]+)/([^.]+.+)   /$1/$2/.www/$3/

把主目录移到新的网页服务器
描述:
有很多网主都有以下问题:在升级时把所有用户主目录由旧的服务器移到新的服务器上。
方法:
使用mod_rewrite可以简单地解决这问题,把所有 /~user/anypathURL重定向至 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
方法:
按以下指令将URL直接对映到档案系统中。

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

重新组织档案系统
描述:
这是一个麻烦的例子:在不用更动现有目录结构下,使用 RewriteRules来显示整个目录结构。背景: net.sw是一个装满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/
我们打算把这个资料夹公开,而且希望直接地显示这资料夹的目录结构,但是我们又不想更改现有目录架构来迁就,加上我们打算开放给FTP,所以不想加入任何网页或CGI程序到这个资料夹中。
方法:
本方法分为两部分:第一部份是编写一系列的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程序来自动更新。第二部份将这资料夹和新建立的CGI、网页配合,我们想将 DATA/稳藏起来,而在用户请求不同URL时执行正确的CGI程序来显示。先将 /net.sw/这URL重定向至 /e/netsw

RewriteRule ^net.sw$       net.sw/        [R]
RewriteRule ^net.sw/(.*)___FCKpd___73nbsp;e/netsw/$1

第一条规则纯粹补加URL结尾的「/」号,而第二条规则就是把URL重定向。之后将下列配置存入 /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   ^___FCKpd___83nbsp;                      netsw-home.cgi     [L]
RewriteRule   ^index/.html___FCKpd___84nbsp;           netsw-home.cgi     [L]
 
# strip out the subdirs when
# the browser requests us from perdir pages
RewriteRule   ^.+/(netsw-[^/]+/.+)___FCKpd___88nbsp;   $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___FCKpd___94nbsp;       -                  [L]
RewriteRule   ^netsw-about/.html___FCKpd___95nbsp;     -                  [L]
RewriteRule   ^netsw-img/.*___FCKpd___96nbsp;          -                  [L]
 
# anything else is a subdir which gets handled
# by another cgi script
RewriteRule   !^netsw-lsdir/.cgi.*     -                  [C]
RewriteRule   (.*)                     netsw-lsdir.cgi/$1

提示:
1.         留意第四部份的L(last)旗标及代表不用更改的('-')符号
2.         留意最后部份第一条规则的 ! (not)字符,及 C (chain) 链接符
3.         留意最后一条规则代表全部更新的语法
以Apache的mod_imap取代NCSA的imagemap
描述:
很多人都想顺利地把旧的NCSA服务器迁至新的Apache服务器,所以我们都想将旧的NCSA imagemap顺利转换到Apache的 mod_imap,问题是 imagemap已被很多超级链接连系着,但旧的 imagemap是存储在 /cgi-bin/imagemap/path/to/page.map,而在Apache却是放在 /path/to/page.map
方法:
我们只要将「 /cgi-bin/」移除便可:

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

在多个目录下搜寻网页
描述:
MultiViews亦不能指示Apache在多个目录里搜寻网页。
方法:
请参看以下指令。

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程序完成,但你却不想用CGI而用URL来传递。
方法:
以下指令将变量及其值抽出URL外,然后记入自设的环境变量中,该变量可由XSSI或CGI存取。例如把 /foo/S=java/bar/转换为 /foo/bar/,然后把「java」写入环境变量「 STATUS」。

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

虚拟用户主机
描述:
你只想根据DNS记录将 www. username .host.domain.com的请求直接对映到档案系统,放弃使用Apache的虚拟主机功能。
方法:
只有HTTP/1.1请求才可用以下方法做到,我们可根据HTTP Header把 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时,就将请求重定向至 www.somewhere.com</CODE。< dd>
方法:
请参看以下指令 :

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

将失败的网页请求重定向至另一部网页服务器
描述:
这是一般常见的疑问,最直观的方法就是用 ErrorDocument加上CGI-scripts更改目标URL,但我们亦可使用mod_rewrite来实行(这方法的效率却比CGI程序更低)。
方法:
再一次留意 CGI会是更有效率的解决方法,而mod_rewrite的好处在于更安全及易设置:

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预计URL改动的功能,所有URL都可以安全地重定向至新的目录,但在速度慢的主机上不宜使用这方法,因为采用本例会拖慢服务器工作,当然你可以在高速CPU主机上使用。
更广泛的URL重定向
描述:
我们想重定向有控制字符的 URL,例如"url#anchor"等,通常Apache会用uri_escape()函数来隔除这些控制字符,因此你不可以直接用mod_rewrite来重定向这类URL。
方法:
我们要使用一 NPH-CGI(NPH = non-parseable headers)程序处理重定向工作,因为NPH-CGI不会隔除控制字符。首先,我们先利用xredirect:

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

强制性将所有URL加上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 "<html>/n";
print "<head>/n";
print "<title>302 Moved Temporarily (EXTENDED)</title>/n";
print "</head>/n";
print "<body>/n";
print "<h1>Moved Temporarily (EXTENDED)</h1>/n";
print "The document has moved <a HREF=/"$url/">here</a>.<p>/n";
print "</body>/n";
print "</html>/n";
 
##EOF##

这样可将所有能或不能直接用mod_rewrite来重定向的URL,经CGI来完成了。例如你可将某URL重定向至新闻服务器

RewriteRule ^anyurl xredirect:news:newsgroup

注意:你不需在每条规则后加上[R]或[R,L]。
多样化资料夹存取
描述:
若你曾浏览 http://www.perl.com/CPAN (CPAN = Comprehensive Perl Archive Network),它会把你重定向至其中一个最近你主机地区的FTP服务器,事实上这应该叫多样化FTP存取。CPAN用CGI来实行这服务,这次我们用mod_rewrite。
<STRONG方法:< strong>
由 mod_rewrite 3.0.0开始可使用「ftp:」重定向至FTP服务器,用户主机的地区可依URL的顶层域名来决定,而顶层域名及FTP服务器位置的对照就存入某档案中。

RewriteEngine on
RewriteMap    multiplex                txt:/path/to/map.cxan
RewriteRule   ^/CxAN/(.*)              %{REMOTE_HOST}::$1                 [C]
RewriteRule   ^.+/.([a-zA-Z]+)::(.*)___FCKpd___165nbsp;${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##

在某段时间执行不同的重定向
描述n:
很多网主仍用 CGI随着不同时间将URL重定向至不同的网页。
方法:
mod_rewrite设有很多以 TIME_xxx开始的环境变量,将这些时间环境变量进行字符串比较可决定重定向至哪个网页:

RewriteEngine on
RewriteCond   %{TIME_HOUR}%{TIME_MIN} >0700
RewriteCond   %{TIME_HOUR}%{TIME_MIN} <1900
RewriteRule   ^foo/.html___FCKpd___178nbsp;            foo.day.html
RewriteRule   ^foo/.html___FCKpd___179nbsp;            foo.night.html

在07:00-19:00就显示foo.day.html,其余时间则显示foo.html
保留旧有文件的URL
描述:
更改文件的扩展名后,如何让旧的 URL能对映到这新的文件。
方法:
把旧的 URL用mod_rewrite重定向至新的文件,若有正确的新文件就对映到这文件,没有的话便对映到原有文件。

#   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___FCKpd___187nbsp;             $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

内容控制
由旧的档名转到新的文件名 (档案系统)
描述:
假设我们将 bar.html改名为 foo.html,而我们又想保留旧有的URL,甚至不想给用户新的URL去连至这新档案。
方法:
将旧的档案对映到新的档案:

RewriteEngine on
RewriteBase    /~quux/
RewriteRule    ^foo/.html___FCKpd___196nbsp;bar.html

由旧的档名转到新的档名 (URL)
描述:
和刚才的例子一样,我们把 bar.html改名为 foo.html,但这次我们想直接将用户的网页重定向至新的文件,即浏览器的URL位置有所改变。
方法:
强制性将 URL对映到新的URL:

RewriteEngine on
RewriteBase    /~quux/
RewriteRule    ^foo/.html___FCKpd___199nbsp;bar.html [R]

由浏览器种类控制内容
描述:
一个出色的网页应能支持各种浏览器,例如我们要把完整版网页传送至 Netscape,但就要传送文字版至Lynx。
方法:
由于浏览器没有提供 Apache格式的浏览器种类资料,所以我们不可使用内文转换(mod_negotiation),我们必需用「User-Agent」决定浏览器种类。例如User-Agent为「Mozilla/3」就把「foo.html」重定向至「foo.NS.html」;若浏览器为「Lynx」或「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程序将最新的档案移到自己的主机上,我们可用webcopy经网页服务器HTTP把档案下载,但这方法有一坏处:只有在执行webcopy时才能更新档案。更好的办法就是在发出请求时立刻找寻最新的档案来源,然后实时下载到自己主机中。
方法:
利用 Proxy Throughput(flag [P])把远程网页甚至整个网站建立一直接对照。

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

 

RewriteEngine on
RewriteBase    /~quux/
RewriteRule    ^usa-news/.html___FCKpd___213nbsp;  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

由内部网络更新档案
描述:
为了安全起见,我们建立了两个网页服务器,第一个是公开的 (www.quux-corp.dom),第二个则是内部使用,受防火墙所保护,一切资料及网站维护都经这个服务器进行,现在我们想令外部服务器能存取穿过防火墙,获取内部服务器已最新的档案。
方法:
我们只容许外部服务器从内部获取资料,一切直接获取的请求都受防火墙拒绝,先在防火墙设定:

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透过proxy throughput获取最新资料:

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[0-5].foo.com这六部服务器的工作量平均分配。
方法:
当然你会有很多方法达成,一般都会使用 DNS,介绍完DNS后再会讨论mod_rewrite如何实行。
1.      DNS循环机制
最简单的方法就是使用BIND的循环机制,e.g.

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.

在DNS层面上这种设定当然是错的,但我们正好使用了BIND的循环机制,BIND接收到www.foo.com的解析请求,然后BIND就会循环地解析作www0-www6,这样就能将用户分配到不同的服务器上,但请记得这不是一个完美的方案,因为其它的域名服务器会快取你服务器的域名解析结果,所以每一次解析到wwwX.foo.com时,都会有很多用户同时被派往同一部服务器,但整体来说已能平衡各服务器的负荷。
2.      DNS平衡负荷
http://www.stanford.edu/~schemers/docs/lbnamed/lbnamed.html有一个lbnamed程序专责利用域名服务器把用户请求分发到不同的服务器上,这是一个用Perl 5及其它附助工具写的复杂DNS工作量分配程序。
3.      代理服务器循环建立机制
我们使用mod_rewrite及其代理服务器网页记录(proxy throughput)功能,先在DNS加入www0.foo.com即是www.foo.com的记录。

www    IN CNAME   www0.foo.com.

然后将www0.foo.com变为一独立代理服务器,即是建立一专责代理服务器,然后把请求分流至五部不同的服务器(www1-www5),我们用lb.pl及以下mod_rewrite规则:

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 (<STDIN>) {
    $cnt = (($cnt+1) % ($last+1-$first));
    $server = sprintf("%s%d.%s", $name, $cnt+$first, $domain);
    print "http://$server/
      
      
mod_rewrite入门
Apache mod_rewrite模块是一个处理URL而又极为复杂的模块,使用mod_rewrite你可处理所有和URL有关的问题,你所付出的就是花时间去了解mod_rewrite的复杂架构,一般初学者都很难实时理解mod_rewrite的用法,有时Apache专家也要mod_rewrite来发展Apache的新功能。
换句话说,当你成功使用mod_rewrite做到你期望的东西,就不要试图再接触mod_rewrite了,因为mod_rewrite的功能实在过于强大。本章的例子会介绍几个成功的例子给你摸索,不像FAQ形式般把你的问题解答。
实用解决方法
这里还有很多未被发掘的解决方法,请大家耐心地学习如何使用mod_rewrite。

注意: 由于各人的服务器的配置都有所不同,你可能要更改设定来测试以下例子,例如使用mod_alias和mod_userdir时要加上[PT],或者使用.htaccess来重定向而非主设定文件等,请尽量理解各例子如何运作,不要生吞活剥地背诵。

URL规划
正规URL
描述:
在某些网页服务器中,一项资源可能会有数个URL,通常都会公布一正规URL(即真正发放的URL),其它URL都会被视为快捷方式或只供内部使用等,无论用户在使用快捷方式或正规URL,用户最后所重定向到的URL必需为正规。
方法:
我们可将所有非正规的URL重定向至正规的URL中,以下例子把非正规的「 /~user」换成正规的「 /u/user」,并且加上「/」号结尾。.

RewriteRule   ^/~([^/]+)/?(.*)    /u/$1/$2 [R]
RewriteRule   ^/([uge])/([^/]+)___FCKpd___1nbsp;/$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被移动
描述:
URL的「/」通常都会映像到DocumentRoot上,但DocumentRoot有时并非重始就限定在某个目录上,它可能只是一个或多个目录的对照而矣。例如我们的内联网址为 /e/www/ (WWW的主目录)和 /e/sww/ (内联网的主目录)等等,因为所有的网页资料都放在 /e/www/目录内,我们要确定所有内嵌的图像都能正确显示。
方法:
我们只要把「 /」重定向至「 /e/www/」,用mod_rewrite来解决比用mod_alias来解决更为简洁,因为URL 别名只会比较 URL 的前部分,但重定向因可能涉及另一台服务器而需要不同的前缀部分(前缀部分已受DocumentRoot限制),所以mod_rewrite是最好的解决方法::

RewriteEngine on
RewriteRule   ^/$ /e/www/ [R]

结尾斜线问题
描述:
每个网主都曾受到结尾斜线问题的折磨,若在URL中没有结尾斜线,服务器就会认为URL无效并返回错误,因为服务器会根据 /~quux/foo去寻找 foo这个档案,而非显示这个目录。其实很多时候,这问题应留待用户自己加「/」去解决,但有时你也可以完成步骤。例如你做了多次URL重定向,而目的地为一个CGI程序。
方法:
最直观的方法就是令Apache自动加上「/」,使用外部重定向令浏览器能正确找到档案,若我们只做内部重定向,就只能正确显示目录页,在这目录页的图像文件会因相对URL的问题而找不到。例如我们请求 /~quux/foo/index.htmlimage.gif时,重定向后会变成 /~quux/image.gif
所以我们应使用以下方法:

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

这方法也适用于.htaccess文件在各目录内设定,但这设定会覆盖原先主配置文件。

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

利用均一的URL版面规划网络群组
描述:
所有的网页服务器都有相同的URL版面,即无论用户向哪个主机发出请求URL,用户都会接收到相同的网页,使URL独立于服务器本身。我们的目的在于如何在Apache服务器不能响应时,都能有一个常规(而又独立于服务器运作)的网页传送给用户,设立网络群组可将这网页送至远程。
方法:
首先,服务器需要一外部文件把网站的用户、用户组及其它资料存储,这文件的格式如下
user1 server_of_user1
user2 server_of_user2
:      :
把以上资料存入 map.xxx-to-host。然后指示服务器把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
当服务器接收到不正确的URL时,服务器会跟随以下指示把URL映像到特定的档案(若URL并没有相对应的记录,就会重定向至 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])/([^/]+)/?___FCKpd___37nbsp;         /$1/$2/.www/
RewriteRule   ^/([uge])/([^/]+)/([^.]+.+)   /$1/$2/.www/$3/

把主目录移到新的网页服务器
描述:
有很多网主都有以下问题:在升级时把所有用户主目录由旧的服务器移到新的服务器上。
方法:
使用mod_rewrite可以简单地解决这问题,把所有 /~user/anypathURL重定向至 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
方法:
按以下指令将URL直接对映到档案系统中。

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

重新组织档案系统
描述:
这是一个麻烦的例子:在不用更动现有目录结构下,使用 RewriteRules来显示整个目录结构。背景: net.sw是一个装满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/
我们打算把这个资料夹公开,而且希望直接地显示这资料夹的目录结构,但是我们又不想更改现有目录架构来迁就,加上我们打算开放给FTP,所以不想加入任何网页或CGI程序到这个资料夹中。
方法:
本方法分为两部分:第一部份是编写一系列的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程序来自动更新。第二部份将这资料夹和新建立的CGI、网页配合,我们想将 DATA/稳藏起来,而在用户请求不同URL时执行正确的CGI程序来显示。先将 /net.sw/这URL重定向至 /e/netsw

RewriteRule ^net.sw$       net.sw/        [R]
RewriteRule ^net.sw/(.*)___FCKpd___73nbsp;e/netsw/$1

第一条规则纯粹补加URL结尾的「/」号,而第二条规则就是把URL重定向。之后将下列配置存入 /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   ^___FCKpd___83nbsp;                      netsw-home.cgi     [L]
RewriteRule   ^index/.html___FCKpd___84nbsp;           netsw-home.cgi     [L]
 
# strip out the subdirs when
# the browser requests us from perdir pages
RewriteRule   ^.+/(netsw-[^/]+/.+)___FCKpd___88nbsp;   $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___FCKpd___94nbsp;       -                  [L]
RewriteRule   ^netsw-about/.html___FCKpd___95nbsp;     -                  [L]
RewriteRule   ^netsw-img/.*___FCKpd___96nbsp;          -                  [L]
 
# anything else is a subdir which gets handled
# by another cgi script
RewriteRule   !^netsw-lsdir/.cgi.*     -                  [C]
RewriteRule   (.*)                     netsw-lsdir.cgi/$1

提示:
1.         留意第四部份的L(last)旗标及代表不用更改的('-')符号
2.         留意最后部份第一条规则的 ! (not)字符,及 C (chain) 链接符
3.         留意最后一条规则代表全部更新的语法
以Apache的mod_imap取代NCSA的imagemap
描述:
很多人都想顺利地把旧的NCSA服务器迁至新的Apache服务器,所以我们都想将旧的NCSA imagemap顺利转换到Apache的 mod_imap,问题是 imagemap已被很多超级链接连系着,但旧的 imagemap是存储在 /cgi-bin/imagemap/path/to/page.map,而在Apache却是放在 /path/to/page.map
方法:
我们只要将「 /cgi-bin/」移除便可:

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

在多个目录下搜寻网页
描述:
MultiViews亦不能指示Apache在多个目录里搜寻网页。
方法:
请参看以下指令。

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程序完成,但你却不想用CGI而用URL来传递。
方法:
以下指令将变量及其值抽出URL外,然后记入自设的环境变量中,该变量可由XSSI或CGI存取。例如把 /foo/S=java/bar/转换为 /foo/bar/,然后把「java」写入环境变量「 STATUS」。

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

虚拟用户主机
描述:
你只想根据DNS记录将 www. username .host.domain.com的请求直接对映到档案系统,放弃使用Apache的虚拟主机功能。
方法:
只有HTTP/1.1请求才可用以下方法做到,我们可根据HTTP Header把 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时,就将请求重定向至 www.somewhere.com</CODE。< dd>
方法:
请参看以下指令 :

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

将失败的网页请求重定向至另一部网页服务器
描述:
这是一般常见的疑问,最直观的方法就是用 ErrorDocument加上CGI-scripts更改目标URL,但我们亦可使用mod_rewrite来实行(这方法的效率却比CGI程序更低)。
方法:
再一次留意 CGI会是更有效率的解决方法,而mod_rewrite的好处在于更安全及易设置:

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预计URL改动的功能,所有URL都可以安全地重定向至新的目录,但在速度慢的主机上不宜使用这方法,因为采用本例会拖慢服务器工作,当然你可以在高速CPU主机上使用。
更广泛的URL重定向
描述:
我们想重定向有控制字符的 URL,例如"url#anchor"等,通常Apache会用uri_escape()函数来隔除这些控制字符,因此你不可以直接用mod_rewrite来重定向这类URL。
方法:
我们要使用一 NPH-CGI(NPH = non-parseable headers)程序处理重定向工作,因为NPH-CGI不会隔除控制字符。首先,我们先利用xredirect:

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

强制性将所有URL加上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 "<html>/n";
print "<head>/n";
print "<title>302 Moved Temporarily (EXTENDED)</title>/n";
print "</head>/n";
print "<body>/n";
print "<h1>Moved Temporarily (EXTENDED)</h1>/n";
print "The document has moved <a HREF=/"$url/">here</a>.<p>/n";
print "</body>/n";
print "</html>/n";
 
##EOF##

这样可将所有能或不能直接用mod_rewrite来重定向的URL,经CGI来完成了。例如你可将某URL重定向至新闻服务器

RewriteRule ^anyurl xredirect:news:newsgroup

注意:你不需在每条规则后加上[R]或[R,L]。
多样化资料夹存取
描述:
若你曾浏览 http://www.perl.com/CPAN (CPAN = Comprehensive Perl Archive Network),它会把你重定向至其中一个最近你主机地区的FTP服务器,事实上这应该叫多样化FTP存取。CPAN用CGI来实行这服务,这次我们用mod_rewrite。
<STRONG方法:< strong>
由 mod_rewrite 3.0.0开始可使用「ftp:」重定向至FTP服务器,用户主机的地区可依URL的顶层域名来决定,而顶层域名及FTP服务器位置的对照就存入某档案中。

RewriteEngine on
RewriteMap    multiplex                txt:/path/to/map.cxan
RewriteRule   ^/CxAN/(.*)              %{REMOTE_HOST}::$1                 [C]
RewriteRule   ^.+/.([a-zA-Z]+)::(.*)___FCKpd___165nbsp;${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##

在某段时间执行不同的重定向
描述n:
很多网主仍用 CGI随着不同时间将URL重定向至不同的网页。
方法:
mod_rewrite设有很多以 TIME_xxx开始的环境变量,将这些时间环境变量进行字符串比较可决定重定向至哪个网页:

RewriteEngine on
RewriteCond   %{TIME_HOUR}%{TIME_MIN} >0700
RewriteCond   %{TIME_HOUR}%{TIME_MIN} <1900
RewriteRule   ^foo/.html___FCKpd___178nbsp;            foo.day.html
RewriteRule   ^foo/.html___FCKpd___179nbsp;            foo.night.html

在07:00-19:00就显示foo.day.html,其余时间则显示foo.html
保留旧有文件的URL
描述:
更改文件的扩展名后,如何让旧的 URL能对映到这新的文件。
方法:
把旧的 URL用mod_rewrite重定向至新的文件,若有正确的新文件就对映到这文件,没有的话便对映到原有文件。

#   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___FCKpd___187nbsp;             $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

内容控制
由旧的档名转到新的文件名 (档案系统)
描述:
假设我们将 bar.html改名为 foo.html,而我们又想保留旧有的URL,甚至不想给用户新的URL去连至这新档案。
方法:
将旧的档案对映到新的档案:

RewriteEngine on
RewriteBase    /~quux/
RewriteRule    ^foo/.html___FCKpd___196nbsp;bar.html

由旧的档名转到新的档名 (URL)
描述:
和刚才的例子一样,我们把 bar.html改名为 foo.html,但这次我们想直接将用户的网页重定向至新的文件,即浏览器的URL位置有所改变。
方法:
强制性将 URL对映到新的URL:

RewriteEngine on
RewriteBase    /~quux/
RewriteRule    ^foo/.html___FCKpd___199nbsp;bar.html [R]

由浏览器种类控制内容
描述:
一个出色的网页应能支持各种浏览器,例如我们要把完整版网页传送至 Netscape,但就要传送文字版至Lynx。
方法:
由于浏览器没有提供 Apache格式的浏览器种类资料,所以我们不可使用内文转换(mod_negotiation),我们必需用「User-Agent」决定浏览器种类。例如User-Agent为「Mozilla/3」就把「foo.html」重定向至「foo.NS.html」;若浏览器为「Lynx」或「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程序将最新的档案移到自己的主机上,我们可用webcopy经网页服务器HTTP把档案下载,但这方法有一坏处:只有在执行webcopy时才能更新档案。更好的办法就是在发出请求时立刻找寻最新的档案来源,然后实时下载到自己主机中。
方法:
利用 Proxy Throughput(flag [P])把远程网页甚至整个网站建立一直接对照。

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

 

RewriteEngine on
RewriteBase    /~quux/
RewriteRule    ^usa-news/.html___FCKpd___213nbsp;  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

由内部网络更新档案
描述:
为了安全起见,我们建立了两个网页服务器,第一个是公开的 (www.quux-corp.dom),第二个则是内部使用,受防火墙所保护,一切资料及网站维护都经这个服务器进行,现在我们想令外部服务器能存取穿过防火墙,获取内部服务器已最新的档案。
方法:
我们只容许外部服务器从内部获取资料,一切直接获取的请求都受防火墙拒绝,先在防火墙设定:

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透过proxy throughput获取最新资料:

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[0-5].foo.com这六部服务器的工作量平均分配。
方法:
当然你会有很多方法达成,一般都会使用 DNS,介绍完DNS后再会讨论mod_rewrite如何实行。
1.      DNS循环机制
最简单的方法就是使用BIND的循环机制,e.g.

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.

在DNS层面上这种设定当然是错的,但我们正好使用了BIND的循环机制,BIND接收到www.foo.com的解析请求,然后BIND就会循环地解析作www0-www6,这样就能将用户分配到不同的服务器上,但请记得这不是一个完美的方案,因为其它的域名服务器会快取你服务器的域名解析结果,所以每一次解析到wwwX.foo.com时,都会有很多用户同时被派往同一部服务器,但整体来说已能平衡各服务器的负荷。
2.      DNS平衡负荷
http://www.stanford.edu/~schemers/docs/lbnamed/lbnamed.html有一个lbnamed程序专责利用域名服务器把用户请求分发到不同的服务器上,这是一个用Perl 5及其它附助工具写的复杂DNS工作量分配程序。
3.      代理服务器循环建立机制
我们使用mod_rewrite及其代理服务器网页记录(proxy throughput)功能,先在DNS加入www0.foo.com即是www.foo.com的记录。

www    IN CNAME   www0.foo.com.

然后将www0.foo.com变为一独立代理服务器,即是建立一专责代理服务器,然后把请求分流至五部不同的服务器(www1-www5),我们用lb.pl及以下mod_rewrite规则:

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 (<STDIN>) {
    $cnt = (($cnt+1) % ($last+1-$first));
    $server = sprintf("%s%d.%s", $name, $cnt+$first, $domain);
___FCKpd___256
}
 
##EOF##

注意,www0.foo.com这服务器的工作量仍然和以前一样高,但这服务器的工作就只是负责分流,所有SSI、CGI、ePerl请求都由其它服务器执行,所以整体的工作量已经减少了许多。
4.      硬件/TCP循环机制
可Cisco的LocalDirector在TCP/IP网络层上把用户请求分流,事实上这种分流程序已刻烙在是电路板上。与硬件有关的解决方法通常都需要大量的金钱,但执行效率就会是最高。
将请求重定向至代理服务器
描述:
(省略)
方法:

##
##  apache-rproxy.conf -- Apache configuration for Reverse Proxy Usage
##
 
#   server type
ServerType           standalone
Port                 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
<Directory />
Options -FollowSymLinks -SymLinksIfOwnerMatch
AllowOverride None
</Directory>
 
#   the status page for monitoring the reverse proxy
<Location /apache-rproxy-status>
SetHandler server-status
</Location>
 
#   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))___FCKpd___322nbsp;to://${server:dynamic}/$1 [S=1]
RewriteRule    ^/(.*)___FCKpd___323nbsp;              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

";
___FCKpd___257
___FCKpd___258
___FCKpd___259

注意,www0.foo.com这服务器的工作量仍然和以前一样高,但这服务器的工作就只是负责分流,所有SSI、CGI、ePerl请求都由其它服务器执行,所以整体的工作量已经减少了许多。
4.      硬件/TCP循环机制
可Cisco的LocalDirector在TCP/IP网络层上把用户请求分流,事实上这种分流程序已刻烙在是电路板上。与硬件有关的解决方法通常都需要大量的金钱,但执行效率就会是最高。
将请求重定向至代理服务器
描述:
(省略)
方法:

___FCKpd___260
___FCKpd___261
___FCKpd___262
___FCKpd___263
___FCKpd___264
___FCKpd___265
___FCKpd___266
___FCKpd___267
___FCKpd___268
___FCKpd___269
___FCKpd___270
___FCKpd___271
___FCKpd___272
___FCKpd___273
___FCKpd___274
___FCKpd___275
___FCKpd___276
___FCKpd___277
___FCKpd___278
___FCKpd___279
___FCKpd___280
___FCKpd___281
___FCKpd___282
___FCKpd___283
___FCKpd___284
___FCKpd___285
___FCKpd___286
___FCKpd___287
___FCKpd___288
___FCKpd___289
___FCKpd___290
___FCKpd___291
___FCKpd___292
___FCKpd___293
___FCKpd___294
___FCKpd___295
___FCKpd___296
___FCKpd___297
___FCKpd___298
___FCKpd___299
___FCKpd___300
___FCKpd___301
___FCKpd___302
___FCKpd___303
___FCKpd___304
___FCKpd___305
___FCKpd___306
___FCKpd___307
___FCKpd___308
___FCKpd___309
___FCKpd___310
___FCKpd___311
___FCKpd___312
___FCKpd___313
___FCKpd___314
___FCKpd___315
___FCKpd___316
___FCKpd___317
___FCKpd___318
___FCKpd___319
___FCKpd___320
___FCKpd___321
___FCKpd___322
___FCKpd___323
___FCKpd___324
___FCKpd___325
___FCKpd___326
___FCKpd___327
___FCKpd___328
___FCKpd___329
___FCKpd___330
___FCKpd___331
___FCKpd___332
___FCKpd___333
___FCKpd___334
___FCKpd___335
___FCKpd___336
___FCKpd___337
___FCKpd___338
___FCKpd___339
___FCKpd___340
___FCKpd___341
___FCKpd___342
___FCKpd___343

 

___FCKpd___344
___FCKpd___345
___FCKpd___346
___FCKpd___347
___FCKpd___348
___FCKpd___349
___FCKpd___350
___FCKpd___351
___FCKpd___352
___FCKpd___353
___FCKpd___354

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值