#logo
PHOTO   GUESTBOOK

前几天在VirtualHost上装了一个TextCube。
这东西很多地方用Rewrite来重写URL美化了URL。
不知道作者的本意是美化还是隐藏其真实路径,但确实简化了PATH_INFO中过长的地址信息。

因为我的TC不是放在站点WEB根目录下的,以后我还想放一些其他目录而且同样想把PATH_INFO简化,所以装了TC后顺便将其Rewrite部分做了些补充和优化。

好像很久没有用这东西了,上一次用这东西好像还是两年前,有些应用还真想不起来。
做完顺便整理了一下Rewrite的应用,算是做个Memo。

一、哪些情况需要使用URL Rewrite
在通常的网站更新和维护中,根据各类需求,会发生服务器转移、维护、目录结构的重新组织、变换URL甚至改变到新的域名等情况。而为了让用户不会因此受到任何影响,最好的方法就是使用URL Rewrite(这里我只讨论Apache的Rewrite模块,mod_rewrite)。
所以,URL Rewrite的最大的好处算是隐藏后台实现了。
这在后台应用平台的迁移时非常有用,对于前台用户来说,根本感觉不到后台应用的变化。

二、Apache Url Rewrite的作用范围
1、Apache主配置文件httpd.conf中;
2、httpd.conf里定义的虚拟主机配置中;
3、Web目录的跨越配置文件.htaccess中(此时所涉及到的目录的AllowOverride设定值需设置成为FileInfo)。

三、Apache URL Rewrite的应用条件
当用户的Web请求最终被导向到某台Web服务器的Apache守护进程,Apache根据配置文件判断该请求是主配置还是虚拟主机,再根据用户在浏览器中请求的URL来匹配Apache URL Rewrite,并且根据实际的请求路径匹配.htaccess中的Apache URL Rewrite,最后把请求的内容传回给用户。该响应可能有2种。
1、将请求内容外部重定向(Redirect)到另一个URL。
让浏览器再次以新的URL发出请求(R=301或者R=302,临时的或是永久的重定向)。
如,一个网站有正规的URL和别名URL,对别名URL进行重定向到正规URL,或者网站改换成了新的域名,则把旧的域名重定向到新的域名。

2、由Apache内部子请求代理产生新的内容送回给用户。
这是Apache内部根据重写后的URL,通过代理模块请求内容并将最终内容送回给客户,客户端浏览器不必再次请求,浏览器中的URL不会被重写,但实际内容由Apache根据Apache URL Rewrite后的URL生成。
例如,在公司防火墙上运行的Apache启动这种代理Apache URL Rewrite,代理对内部网段上的Web服务器的请求。

四、应用事例

mod_rewrite

首先,可以使用rewrite的前提是确定加载了 mod_rewrite 模块。

Apache 1.x 需要确认 conf/httpd.conf 中有如下两段代码,且注释已被去掉:

  LoadModule rewrite_module libexec/mod_rewrite.so
  AddModule mod_rewrite.c

Apache 2.x 需要确认 conf/httpd.conf 中有如下代码,且注释已被去掉:

LoadModule rewrite_module modules/mod_rewrite.so

mod_rewrite指定和语法,设定值:

指令 语法 默认值
RewriteEngine RewriteEngine on|off Off
RewriteOptions RewriteOptions Option MaxRedirects=10
RewriteLog RewriteLog file-path None
RewriteLogLevel RewriteLogLevel Level RewriteLogLevel 0
RewriteLock RewriteLock file-path None
RewriteMap RewriteMap MapName MapType:MapSource Notused per default
RewriteBase RewriteBase URL-path physical directory path
RewriteCond RewriteCond TestString CondPattern None
RewriteRule RewriteRule Pattern Substitution None

其中:

RewriteEngine 为开关重构引擎
RewriteOptions 设置一些特殊参数
RewriteLog 为设定重写log文件
RewriteLogLevel 设置日志级别
RewriteLock 设置RewriteMap程序的同步锁文件
RewriteMap 定义重写影射
RewriteBase 设置目录范围内重写的基本URL
RewriteCond 定义规则条件,可以通过检查HTTP_REFERER,REQUEST_FILENAME,HTTP_HOST等实现。-f表示硬盘中存在此文件,!-f表示文件不存在。
RewriteRule 定义重写规则


假定Apache被编译安装在主机192.168.1.xx的/usr/local/apache目录下面,同时编译了重写和代理模块。

1、隐藏Apache下的某个目录,使得对该目录的任何请求都重定向到另一个文件

(1)httpd.conf的实现方法

我们将下面的部分放到/usr/local/apache/conf/httpd.conf中。

< Directory “/usr/local/apache/htdocs/manual/”>
   options Indexes followsymlinks
   allowoverride all
   rewriteengine on
   rewritebase /
   rewriterule ^(.*)$ index.html.en [R=301]
< /Directory >

注:“rewriteengine on”为重写引擎开关,如果设为“off”,则任何Apache URL Rewrite定义将不被应用,该开关的另一用处就是如果为了临时去掉Apache URL Rewrite,可以将引擎开关设为“off”再重新启动Apache即可,不必将其中的各条Apache URL Rewrite注释掉。

“rewritebase /”的作用是如果在下面的rewriterule定义中被重写后的部分(此处为文件名index.html.en)前面没有“/”,则表明是相对目录,相对于这个rewritebase后面的定义也就是/usr/local/apache/htdocs/index.html.en,否则,如果此处没有“rewritebase /”这一项,则被重写成http://192.168.1.xx/usr/local/apache/htdocs/manual/index.html.en,显然是不正确的。

我们也可以不用“rewritebase /”,而是将其改为如下部分。

rewriteengine on
rewriterule ^(.*)$ /index.html.en [R=301]

或者更改为:

rewriteengine on
rewriterule ^(.*)$ http://192.168.1.xx/index.html.en [R=301]

(2).htaccess的实现方法

我们将下面的部分放到httpd.conf中。

< Directory “/usr/local/apache/htdocs/manual/”>
   options Indexes followsymlinks
   allowoverride all
< /Directory >

然后将下面的部分放到/usr/local/apache/htdocs/manual/.htaccess中。
注: 对文件.htaccess所做的任何改动不需要重启动Apache。

rewriteengine on
rewritebase /
rewriterule ^(.*)$ index.html.en [R=301]

还可以利用.htaccess方案将这个manual目录重定向到用户phpoa自己的主目录。

rewriteengine on
rewritebase /~phpoa/
rewriterule ^(.*)$ $1 [R=301]

这样,对manual目录下任何文件的请求被重定向到~phpoa目录下相同文件的请求。

2、将http://www.username.domain.com对于username的主页请求转换为对http://www.domain.com/username的请求对于HTTP/1.1的请求包括一个Host: HTTP头,我们能用下面的规则集重写http://www.username.domain.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

注: “rewritecond”表明是条件Apache URL Rewrite,当满足后面定义的条件后才会应用下面的重写规
则,“rewritecond”有各种变量,请查阅相关文档。

3、防火墙上的Apache Url Rewrite代理内部网段上服务器的请求

NameVirtualhost 1.2.3.4

< Virtualhost 1.2.3.4:80 >
    servername www.domain.com
    rewritengin on
    proxyrequest on
    rewriterule ^/(.*)$ http://192.168.1.3/$1 [P,L]
< /Virtualhost >

注: 当外部浏览器请求http://www.domain.com时,将被解析到IP地址1.2.3.4,Apache交由mod_rewrite处理,转换成http://192.168.1.3/$1后再交由代理模块mod_proxy,得到内容后传送回用户的浏览器。

4、基本预先设定的转换Map表进行重写rewritemap

转换http://www.domain.com/{countrycode}/anypath到Map表中规定的URL,前面是虚拟主机中的定义。

rewritelog /usr/local/apache/logs/rewrite.log
rewriteloglevel 9
rewriteengine on
proxyrequest on
rewritemap sitemap txt:/usr/local/apache/conf/rewrite.map
rewriterule ^/([^/] ) /(.*)$ http://%{REMOTE_HOST}::$1 [C]
rewriterule (.*)::([a-z] )$ ${sitemap:$2|http://h.i.j.k/} [R=301,L]

文件/usr/local/apache/conf/rewrite.map的内容如下:

sg http://a.b.c.d/
sh http://e.f.g.h/

注: 当用户请求http://www.domain.com/sg/anypath时被重写为http://a.b.c.d/anypath。当
需要调试时请用rewritelog和 rewriteloglevel 9联合,9为最大,即得到最多的调试信息;最小为1,表示得到最少的调试信息;默认为0,表示没有调试信息。



Some quick stuff:

在REWRITE的设定中会使用很多正则表达式,下面是一些最基本的正则表达式;

  • ([a-z]+) - just small letters
  • ([A-Z]+) - just big letters
  • ([0-9]+) - just numbers
  • ([a-zA-Z_-]+) - small and big letters and minus (-)
  • ([a-zA-Z0-9_-]+) - small and big letters, numbers and minus (-)
  • (.*) - everything - warning!!!! don't ever use - this have to much permissions



注:apache官方不建议使用.htaccess方式,可能是出于安全性的考虑吧。

2008/03/26 02:44 2008/03/26 02:44
#fist posted at 2008/03/26 02:44
No Trackback, Comments (2)

trackback url (click to copy):
Cannot send a trackbact to this post.