重写规则以防止 apache 在到达 htaccess 之前解码 url?



我们有这样的htaccess规则:

RewriteRule ^(.*)/(.*)/(.*) ../app$1/scripts/api/index.php?fn=$2&$3 [L]

这在大多数情况下都很好用,但是,Apache在到达此规则之前对url进行了解码,因此像beta/list/&cat=red%20%26%20blue这样的url被htaccess视为beta/list/&cat=red & blue,因此我们得到了cat='red',并且blue=null进入index.php而不是cat='red & blue'

我已经读到这个问题的解决方法是在 htaccess 规则中使用像%{REQUEST_URI}%{THE_REQUEST}这样的服务器变量,因为这些变量在使用前没有解码,但很难实现。重写规则中的问号让一切都变得疯狂,我不知道如何摆脱它。

有专家可以帮助我修复下面的规则,使其表现得像上面一样吗?

RewriteCond %{REQUEST_URI} ^(.*)/(.*)/(.*)
RewriteRule . ../app%1/scripts/api/index.php?fn=%2&%3 [L]

事实上,解决方案是使用名为THE_REQUEST的特殊服务器变量

。从mod_rewrite文档中:

THE_REQUEST

浏览器发送到服务器的完整 HTTP 请求行(例如, "GET/index.html HTTP/1.1"(。这不包括任何额外的 浏览器发送的标头。此值尚未取消转义 (解码(,与下面的大多数其他变量不同。

以下是您的规则应如下所示

# don't touch urls ending by index.php
RewriteRule index.php$ - [L]
# user request matching /xxx/xxx/xxx (with optional query string)
RewriteCond %{THE_REQUEST} s/([^/?]+)/([^/?]+)/([^?]+)(?:s|?) [NC]
RewriteRule ^ ../app%1/scripts/api/index.php?fn=%2&%3 [L,QSA]

请注意,您不应该使用相对路径进行内部重写,这可能会导致混淆。相反,定义一个RewriteBase,使用绝对路径或从域根开始,/

更新

由于您可以在 url 中使用编码的正斜杠,因此您需要将AllowEncodedSlashes设置为NoDecode(或On,但这不安全(。另请注意,由于错误,您必须将此指令放在虚拟主机上下文,即使服务器配置上下文被认为是正常的(否则,它将被简单地忽略(。默认情况下,AllowEncodedSlashes设置为Off。因此,Apache 会自动处理编码的斜杠并拒绝它们,而不会将请求传递给mod_rewrite。请参阅此处的官方文档。

最新更新