@ZEAL Blog·厉
We stand alone,
TOGETHER.

Apache mod_rewrite 之目录冲突

Posted by zeal on 2006-07-14 11:46 , 1159 characters |  + 0 - 1   English
转载请保留本行原始出处声明信息 : http://www.zeali.net/entry/405 MaDe1nZEAL
标签 ( WebDev ):  , 

  现象:在 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 的文档地址与操作系统的目录结构发生冲突。

Last Modified on 2007-05-28 14:12
6 条评论:
- surain2006-09-02 23:01
请教一个规则怎么写。
我先用了一个alias:Alias /bbs/ "/www/public-html/dz/" (因为服务器的根是/www/public-html/web/),
然后我需要把这样的网址http://test.com/bbs/forum-116-1.html重..
我试了不少规则,都是说“HTTP 404 - 未找到文件”。
先谢谢。
- surain2006-09-03 13:25
请教一个规则怎么写。
我先用了一个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 - 未找到文件”。
先谢谢了。
- zeal (link) 于 2006-09-04 11:41
RewriteRule ^/bbs/forum-([0-9]+)-([0-9]+).html$ /bbs/forumdisplay.php?tid=$1&page=$2 [PT]

'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就是个典型的例子。
- nickfan () (link) 于 2006-11-02 14:33
不知道楼主有否办法解决这个问题:

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也能正常实现类似于最顶上的那个需求。
- zeal (link) 于 2006-11-02 16:14
我怀疑是否因为 apache 2.0 配置文件里面对于目录缺省是使用了
Options Indexes FollowSymLinks
这样当找不到默认的index文件之后就触发了 Indexes 模块的功能,转到 apache 提供的目录列表去了。
你可以试试把 Indexes 给去掉看看。
- paomian (link) 于 2007-04-25 19:31
zeal这篇博客中所说的问题,我也碰到过,系统根目录的优先级别确实比网站根目录要高一些,目前也不清楚为什么。手册中也没有提及这个。
Since 2005.04.27  梦想 就像鸡蛋 要么孵化 要么臭掉RSS Feed (Entries) | Back To Home | @ZEAL | 沪ICP备05024379号