编辑:[已解决]最终在文档中找到了解决方案;发布了答案。简而言之:标志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 输出到脚本来检查它们,但这里有一种在线重现该问题的方法。
如何在线重现此问题
- 转到此在线 htaccess 测试器
- 对于 URL,输入
http://example.com/a/123/b
对于规则,粘贴此内容:
# 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
- 运行:输出为
http://example.com/my_a/123/b
- 取消注释第二行。
- 运行:输出为
http://example.com/mo_123:123:123/b
- 注释掉第二行,将第一行改为
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 所著称的臃肿和不确定性。