6

目标:

在共享 Apache 2.2 机器上的虚拟服务器中,我尝试配置.htaccess为无缝表示文件夹子文件夹中的public_html文件,就好像它们在根目录中一样。

也就是说,http://www.example.com/home用户访问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,并且浏览器地址栏会显示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 (没有尾部斜杠),它会重定向到www.example.com/subfolder/contact/,这是我不想要的。

我觉得这应该告诉我出了什么问题,但答案仍然不知道。

4

1 回答 1

16

发生这种情况的原因是因为mod_dir。它有一个名为的指令DirectorySlash,当它认为对目录发出请求并且尾部斜杠丢失到带有尾部斜杠的相同 URI 时,它会重定向浏览器。问题是 mod_dir 和 mod_rewrite 在 URL/文件映射管道中的不同位置应用。所以 mod_rewrite 会在某一时刻破坏 URI,然后当 mod_dir 执行它的操作时,重写的 URI 会被重定向,因此浏览器地址栏中的 URL 会更改为包含“隐藏”的内部重写。

你可以在这里做几件事。

  1. 您可以在 mod_rewrite 中自己强制使用尾部斜杠,因此在URI 到达 mod_dir之前,浏览器会被重定向以包含尾部斜杠。这意味着您的所有 URL/home/contact将包含一个尾部斜杠,如果缺少一个,您的重写代码将重定向并添加一个。像这样,您当前的规则之上,以便首先应用它:

    RewriteCond %{REQUEST_URI} !^/subfolder
    RewriteCond %{DOCUMENT_ROOT}/subfolder%{REQUEST_URI} !-f
    RewriteRule ^(.*[^/])$ /$1/ [L,R=301]
    
  2. 关闭DirectorySlash以便 mod_dir 停止执行此重定向。您可以简单地包含DirectorySlash Off在您的 htaccess 文件的顶部。但是,这里的缺点是缺少尾部斜杠时可能存在信息泄露安全问题。


编辑:

为了使用没有尾部斜杠的索引文件,您需要映射到它。尝试将您的规则更改为:

    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]
于 2012-12-27T21:10:01.633 回答