要么孵化 要么臭掉
Apache mod_rewrite 之目录冲突
现象:在 VirtualHost 配置块中启用 RewriteEngine ,进行 url rewrite ,结果发现重写到某一个目录下的url总是报错,说是 url 不存在。但通过实际的动态url去访问一切正常。
httpd-vhost.cnf相关配置如下:
<VirtualHost *:80>
ServerAdmin noname@gmail.com
DocumentRoot /www/html/scripts
ServerName scripts.zeali.net
ErrorLog /logs/scripts.zeali.net-error_log
CustomLog /logs/scripts.zeali.net-access_log common
<IfModule rewrite_module>
RewriteEngine On
RewriteRule /entry/([0-9]+)\.html /live/entry.php?id=$1
</IfModule>
</VirtualHost>
反复测试,发现如果把 /www/html/scripts 下的 live 目录重命名成其他的名字, url rewrite 就完全正常。难道说 live 是 mod_rewrite 的关键字?不太可能。继续检查,发现在操作系统的根目录下存在一个同名的 live 目录。把这个目录删除之后, rewrite 恢复正常。
结论: mod_rewrite 在执行 RewriteRule 的时候首先寻找的是操作系统的目录层次,而不是 DocumentRoot 下的相对目录层次;因此如果不幸在 DocumentRoot 目录下存在与操作系统根目录下一样的目录, mod_rewrite 将不会正确的找到 rewrite 的目标 url 。Updated 2006-07-18 14:40 -- 如果使用 .htaccess 文件设置 RewriteRule 的话,因为使用的是相对目录形式,就不会存在这个问题。
目前暂时找不到明确的文档来印证这个问题,或者说我对 mod_rewrite 的理解太浅。希望能看到更准确的说法来诠释这个现象。在此之前,只能认为这是 mod_rewrite 设计上的问题,注意不要让需要加入 RewriteRule 的文档地址与操作系统的目录结构发生冲突。

我先用了一个alias:Alias /bbs/ "/www/public-html/dz/" (因为服务器的根是/www/public-html/web/),
然后我需要把这样的网址http://test.com/bbs/forum-116-1.html重..
我试了不少规则,都是说“HTTP 404 - 未找到文件”。
先谢谢。
我先用了一个alias:Alias /bbs/ "/www/public-html/dz/" (因为服务器的根是/www/public-html/web/),
然后我需要把这样的网址http://test.com/bbs/forum-116-1.html 重定向为http://test.com/bbs/forumdisplay.php?tid..
我试了不少规则,都是说“HTTP 404 - 未找到文件”。
先谢谢了。
'passthrough|PT' (移交给下一个处理器 pass through)
此标记强制重写引擎将内部结构request_rec中的uri字段设置为 filename字段的值,它只是一个小修改,使之能对来自其他URI到文件名翻译器的 Alias,ScriptAlias, Redirect 等指令的输出进行后续处理。举一个能说明其含义的例子: 如果要通过mod_rewrite的重写引擎重写/abc为/def, 然后通过mod_alias使/def转变为/ghi,可以这样:
RewriteRule ^/abc(.*) /def$1 [PT]
Alias /def /ghi
如果省略了PT标记,虽然mod_rewrite运作正常, 即, 作为一个使用API的URI到文件名翻译器, 它可以重写uri=/abc/...为filename=/def/..., 但是,后续的mod_alias在试图作URI到文件名的翻译时,则会失效。
注意: 如果需要混合使用不同的包含URI到文件名翻译器的模块时, 就必须使用这个标记。。 混合使用mod_alias和mod_rewrite就是个典型的例子。
apache 2.0 与2.2 rewrite 模块和默认文档优先问题
服务器ubuntu 6.06 server LTS
apache 2.0.55
apache 2.2.3
都开启了默认文档和rewrite模块
DirectoryIndex index.html index.htm index.php
rewrite规则:
RewriteRule ^index.(html|htm|php)$ apps/index.php [L]
首页文档index.html文件存在且可读
主机域名www.testdomain.com
原本意愿是
访问 http://www.testdomain.com 即可通过rewrite去自动访问apps/index.php而不是/index.html真实文件 [实际需求]
在实际当中做了几次试验apache2.2和2.0在默认文档上的重写表现不同(其他重写规则执行都正常和相同):
2.2当中
(1) .htaccess方式rewrite 有/index.html文件 浏览器结果:访问http://www.testdomain.com/显示的是ap..
(2) .htaccess方式rewrite 无/index.html文件 浏览器结果forbidden 403
2.0当中
(3) .htaccess方式rewrite 有/index.html文件 浏览器结果:访问http://www.testdomain.com/显示的是/i..
(4) .htaccess方式rewrite 无/index.html文件 浏览器结果:访问http://www.testdomain.com/显示的是ap..
把重写规则写入vhosts的段落当中情况同(3)(4)。
不知道是不是在2.0下重写模块和默认文档的优先级和2.2下的不一样
我猜测了一下目前【我的环境】的请求执行流程:
2.2流程:
1)浏览器发送GET /请求
2)服务器查找DirectoryIndex 中的默认文档是否在/路径下存在
3)找到index.html,将请求变为 GET /index.html
4)发现GET /index.html 符合rewrite规则,执行重写规则
5)返回的是/apps/index.php解析执行的结果
6)终止
2.0流程:
1)浏览器发送GET /请求
2)服务器查找DirectoryIndex 中的默认文档是否在/路径下存在
3)找到index.html,解析/index.html返回结果
4)终止
相差的就是找到 默认文档列表(DirectoryIndex)中的文件之后的行为,2.0直接解析找到的默认文档并返回而2.2却是继续去执行mod_rewrite模块的任务(.htaccess指定的规则)然后再返回。
不知道能不能让2.0的apache在默认文档上的rewrite也能正常实现类似于最顶上的那个需求。
Options Indexes FollowSymLinks
这样当找不到默认的index文件之后就触发了 Indexes 模块的功能,转到 apache 提供的目录列表去了。
你可以试试把 Indexes 给去掉看看。