目标:
在共享Apache 2.2框上的虚拟服务器中,我尝试配置.htaccess
以无缝地表示public_html
文件夹的子文件夹中的文件,就像它们位于根目录中一样。
也就是说,当用户访问http://www.example.com/home
时,我需要他或她无缝地(不在客户端浏览器中重写URL)查看来自http://www.example.com/subfolder/home
的文件。
我的.htaccess
文件如下所示:
RewriteEngine on
RewriteRule !^subfolder/ subfolder%{REQUEST_URI}
问题:
这可行,但它会在客户端浏览器中重写URL。
也就是说,用户会在地址栏中看到http://www.example.com/subfolder/home/
,但我需要他们才能看到http://www.example.com/home
我的理解是,我在.htaccess
中所做的事情应该导致对最终用户不可见的“内部”重写,但看起来我正在进行“外部”重写。
我做错了什么?
[编辑]其他详细信息:
当用户访问www.example.com
时, 按需运行,因为用户会看到从public_html/subfolder/default.html
投放的主页内容,并且浏览器地址栏显示{ {1}}。
但是,当用户点击该主页上的“联系”链接(编码为www.example.com
)时,它会到达,但会在浏览器地址栏中显示href="/contact"
,就像它已经完成了重定向而不是内部重写。
如果我然后删除地址栏中的www.example.com/subfolder/contact/
文字并强制重新加载页面,则可以正常运行 - 它会加载正确的内容,地址栏仍为/subfolder
实施说明:如果有帮助,www.example.com/contact/
是包含public_html/subfolder/contact
文件的文件夹。
另一个观察结果:
如果我打开一个新标签页并输入default.html
(请注意尾随斜杠),它会按预期和期望运行。
但是,如果我打开一个新标签并输入www.example.com/contact/
(没有尾随斜杠),它会重定向到www.example.com/contact
,这是我不想要的。
我觉得应该告诉我出了什么问题,但答案仍然没有找到我。
答案 0 :(得分:14)
之所以发生这种情况,是因为mod_dir
。它有一个名为DirectorySlash
的指令,当它认为对某个目录发出请求时,会重定向浏览器,并且相同的URI缺少尾部斜杠,并附加一个尾部斜杠。问题是mod_dir和mod_rewrite应用于URL /文件映射管道中的不同位置。所以mod_rewrite在某一点上破坏了URI,然后当mod_dir做了它的事情时,重写的URI被重定向,因此浏览器地址栏中的URL改变为包含“隐藏的”内部重写。
你可以在这里做几件事。
您可以在mod_rewrite中自行强制使用尾部斜杠,这样浏览器就会被重定向,以便在 URI到达mod_dir之前包含尾部斜杠。这意味着您/home
和/contact
之类的所有网址都会包含一个尾部斜杠,如果缺少一个斜杠,您的重写代码将重定向并添加一个。像这样,上面你当前的规则,以便首先应用它:
RewriteCond %{REQUEST_URI} !^/subfolder
RewriteCond %{DOCUMENT_ROOT}/subfolder%{REQUEST_URI} !-f
RewriteRule ^(.*[^/])$ /$1/ [L,R=301]
关闭DirectorySlash
,以便mod_dir停止执行此重定向。您只需在htaccess文件的顶部添加DirectorySlash Off
即可。但是,当缺少尾部斜杠时,此处的缺点是a possible information disclosure security issue。
编辑:
为了使用索引文件而不使用尾部斜杠,您需要映射到它。尝试将规则更改为:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/subfolder
RewriteCond %{DOCUMENT_ROOT}/subfolder%{REQUEST_URI} -d
RewriteRule ^(.*?)/?$ /subfolder/$1/ [L]
RewriteCond %{REQUEST_URI} !^/subfolder
RewriteRule ^(.*)$ /subfolder/$1 [L]