今天遇到一个非常紧急的问题,看起来也很常见,就是网站的一个子模块不是直接提供服务的,而是在public子目录下提供网页,然而不能把public带进URL里面,就是说我的URL应该是这样的/submodule/index.html,文件地址应该是这样的submodule/public/index.html

然而网站结构前期已经定好,不能直接把public子目录配置为网站的根目录(这个模块本身就在网站根目录的子目录下面),所以需要在这个模块的目录下配置重写规则rewrite到public子目录。于是乎,我想当然的配置了如下.htaccess:

1
2
3
4
5
6
<IfModule mod_rewrite.c>
Options +FollowSymlinks -Multiviews
RewriteEngine On

RewriteRule ^(.*)$ public/$1
</IfModule>

然而Apache却报了500错误,查日志,Rewrite次数过多。什么意思呢?就是在第一次进入子模块目录时,加上了一个public之后,会从头再来一次,再一次进入这个目录,继续重写,无限循环,就爆炸了。怎么办?实测在Rule后面加L标记是无效的。

Google搜索:Apache如何rewrite到子目录,无果。我就纳闷了,这个需求应该很常见吧,怎么就搜不到呢?再搜英文,依然无果。难道是我的打开方式不对?

折腾了很久,最后终于发现一个神器(所谓神奇就是不知道为什么就可以了):

1
2
3
4
5
6
7
<IfModule mod_rewrite.c>
Options +FollowSymlinks -Multiviews
RewriteEngine On

RewriteRule ^public(.*)$ - [L]
RewriteRule ^(.*)$ public/$1
</IfModule>

两条Rule依次执行,当发现当前URL已经有了public,直接中断查询,于是就不会溢出了(中间的-意思是只匹配不替换),大概可能是这样?最后我试了一下,子目录再子目录也是可以的,只要再复制一份.htaccess到子目录就行了。