【问题标题】:.htaccess rewrite to subfolder.htaccess 重写到子文件夹
【发布时间】:2012-12-12 15:41:24
【问题描述】:

目标:

在共享 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 提供的主页内容,并且浏览器地址栏显示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/,这是我不想要的。

我觉得这应该告诉我出了什么问题,但我仍然无法找到答案。

【问题讨论】:

  • 你还有什么规定吗?您确定重定向时没有尾部斜杠吗?
  • public_html 目录中是否有您也需要访问的文件,或者子文件夹中的所有文件?
  • @JonLin,我没有其他规则,是的,我错过了一个斜杠,所以我编辑了这个问题。
  • @JennyD,public_html 中没有我还需要访问的任何文件。 public_html 目录包含 .htaccess 文件和多个文件夹,其中一个包含我的主 example.com 站点,其他包含子域站点。

标签: apache .htaccess apache2 rewrite


【解决方案1】:

发生这种情况的原因是因为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 停止执行此重定向。您可以在 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]

【讨论】:

  • 非常感谢,乔恩。鉴于您的解决方案的简单性、站点的简单性以及我缺乏安全问题,我喜欢选项 #2。当我将DirectorySlash Off 添加到.htaccess 的头部时,我开始在除主页之外的所有页面上收到Forbidden 失败。服务器错误日志显示很多Directory index forbidden by Options directive 失败。想法?
  • 我是否正确理解您的编辑提供了一个不能与DirectorySlash On 结合使用的“选项#3”?
  • @briguy328 不,你离开DirectorySlash Off,但你需要在内部重写中添加一个斜杠,这样自动索引就不会启动。
  • 谢谢!这更接近,因为正确的页面总是在地址栏中加载所需的 URL,但现在没有图像加载。错误日志显示现在在图像文件名的末尾附加了斜杠(例如 /images/header.jpg/ 而不是 /images/header.jpg
  • @briguy328 这个好像比以前复杂了,看上面的编辑
猜你喜欢
  • 2015-09-27
  • 2014-06-30
  • 2012-11-20
  • 2011-03-02
  • 2016-12-21
  • 2012-11-22
  • 1970-01-01
  • 2021-11-20
  • 2014-01-13
相关资源
最近更新 更多