mod_rewrite 神秘地将子文件夹附加到重写的 URL

mod_rewrite 神秘地将子文件夹附加到重写的 URL

编辑:[已解决]最终在文档中找到了解决方案;发布了答案。简而言之:标志DPI

编辑:在底部添加了一个简单的在线重现问题的方法。

我花了几个小时调试一些重写。一切都很好,除了一个行为让我困惑。

不知何故,当输入包含两个或更多子目录的 URL 时,mod_rewrite 会自动将所有子目录(第一个除外)附加到重写的 URL。这是我能简化的最简单的示例。它位于 的 htaccess 中DOCUMENT_ROOT

  • 网址:http://localhost/stripthis/stripthat
  • RewriteRule ^ RewriteWasHere_
  • 输出:RewriteWasHere_/stripthat

这是怎么stripthat回事?上游的某些选项可能导致了这种情况吗?

我尝试使用各种规则来删除子文件夹。例如:

  • 网址:http://localhost/stripthis/stripthat
  • RewriteRule ^/?([^/]+) RewriteWasHere_$1
  • 输出:RewriteWasHere_stripthis/stripthat

奇怪的是,这在本地 xampp x Apache 2.4.7 和远程 CentOS x Apache 2.2 上都发生。

我一直在通过将重写的 URL 输出到脚本来检查它们,但这里有一种在线重现该问题的方法。

如何在线重现此问题

对于规则,粘贴此内容:

# the `(?!)` negative lookaheads are just to make triple sure
# we're not running the same rules multiple times
RewriteRule ^(?!m[yo])([^/]+) my_$1
#RewriteRule ^(?!mo])\D*(\d+) mo_$1:$1:$1
  1. 运行:输出为http://example.com/my_a/123/b
  2. 取消注释第二行。
  3. 运行:输出为http://example.com/mo_123:123:123/b
  4. 注释掉第二行,将第一行改为RewriteRule ^(?!m[yo])([^/]+).*$ my_$1:该问题在此站点上消失,但在我的服务器上仍然存在。

任何见解都将不胜感激。

答案1

[DPI](丢弃路径信息)

经过几个小时的测试和困惑之后,我回到了文档并找到了解决方案:[DPI]旗帜。

DPI 标志导致重写 URI 的 PATH_INFO 部分被丢弃。

此标志在 2.2.12 及更高版本中可用。

在每个目录上下文中,每个 RewriteRule 比较的 URI 是 URI 和 PATH_INFO 的当前值的串联。

当前 URI 可以是客户端请求的初始 URI,也可以是上一轮 mod_rewrite 处理的结果,或者是当前轮 mod_rewrite 处理中前一个规则的结果。

相比之下,每个规则之前附加到 URI 的 PATH_INFO 仅反映此轮 mod_rewrite 处理之前的 PATH_INFO 值。因此,如果 URI 的大部分内容在多个 RewriteRule 指令中匹配并复制到替换中,而不考虑 URI 的哪些部分来自当前 PATH_INFO,最终 URI 可能会附加多个 PATH_INFO 副本。

在任何替换中使用此标志,其中 PATH_INFO 是此请求到文件系统的先前映射所产生的,不重要。此标志将永久忘记在此轮 mod_rewrite 处理开始之前建立的 PATH_INFO。在当前轮 mod_rewrite 处理完成之前,不会重新计算 PATH_INFO。此轮处理期间的后续规则将仅看到替换的直接结果,而不会附加任何 PATH_INFO。

答案2

$也许您的表达中缺少尾随RewriteRule,因此内容没有完全匹配?

您可能需要考虑切换到 nginx;它具有非常清晰和合理的文档,而没有 Apache 所著称的臃肿和不确定性。

相关内容