mod_rewrite神秘地追加子文件夹重写URL

编辑:[解决]最后在文档中find解决scheme; 张贴了一个答案。 简而言之: DPI标志。

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

我花了几个小时debugging一些重写。 一切都很好,只有一种行为让我感到困惑。

不知何故,当一个URL有两个或更多的子目录时,mod_rewrite自动将所有的子目录(除了第一个)附加到重写的url。 这是我可以减less的最简单的例子。 这是在DOCUMENT_ROOT的htaccess。

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

那条stripthat从哪里来的? 上游有一些select可能导致这种情况吗

我试图用各种规则剥离子文件夹。 例如:

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

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

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

如何重现此在线

  • 去这个在线htaccesstesting
  • 对于该url,请inputhttp://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 
  1. 运行:输出是http://example.com/my_a/123/b
  2. 取消第二行的注释。
  3. 运行:输出是http://example.com/mo_123:123:123/b
  4. 注释掉第二行,将第一行更改为RewriteRule ^(?!m[yo])([^/]+).*$ my_$1 :问题在本站点消失,但在我的服务器上消失。

任何深刻的见解将深受赞赏。

[DPI](discardpathinfo)

经过数小时的testing和困惑之后,我又回到了文档 ,发现了解决scheme: [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指令中的replace中,而不考虑URI的哪些部分来自当前的PATH_INFO,则最终的URI可能具有追加到其上的多个PATH_INFO副本。

在任何replace处使用此标志,其中由此请求到文件系统的先前映射导致的PATH_INFO不重要。 这个标志永久忘记了在这一轮mod_rewrite处理开始之前build立的PATH_INFO。 在当前一轮mod_rewrite处理完成之前,PATH_INFO将不会被重新计算。 在这轮处理过程中的后续规则将只看到replace的直接结果,没有附加任何PATH_INFO。

也许你错过了你的RewriteRuleexpression式中的尾部$ ,因此东西没有完全匹配?

你可能要考虑切换到nginx; 它有一个非常清晰和合理的文件,没有阿帕奇相当出名的膨胀和不确定性。