我今天更新了 Apache(至 2.4.56-1),以前可以正常工作的大量 .htaccess 重写现在出现 AH10411 错误,与查询中的空格有关。我正在寻找“正确”的解决方案……
我今天更新了 Apache(至 2.4.56-1),以前可以正常工作的大量 .htaccess
重写现在都收到 AH10411 错误,与查询中的空格有关。我正在寻找“正确”的解决方案。
用户点击一个链接,如 <a href='FISH%20J12345.6-78919'>clickme</a>
你所见,链接 URL 中的空格已被编码为 %20
.
相关服务器目录中的文件包含并执行该相关指令 .htaccess
:
RewriteRule ^(FISH\s*J[0-9\.]+-?\+?[0-9]+)$ myPage.php?sourceName=$1 [L,QSA]
(在上面,我检查的是空格,而不是 %20
,因为浏览器似乎在满足此规则之前将其转换为空格)。
在我更新 Apache 之前,这个功能一直有效;现在用户收到 403 错误,并且我的 Apache 错误日志报告:
AH10411:重写的查询字符串包含控制字符或空格
这似乎是一个新的错误,因为用谷歌搜索没有找到任何结果!
编辑我的页面(例如)将空格更改为下划线并正确处理它实际上不是一个选择,因为设计旨在支持用户能够使用他们关心的对象的名称直接输入 URL。到目前为止,我发现的唯一解决方法有点丑陋,即在正则表达式中分别捕获源名称的两个部分,因此:
RewriteRule ^(FISH)\s*(J[0-9\.]+-?\+?[0-9]+)$ myPage.php?sourceName=$1+$2 [L,QSA]
^ ^ ^^^
(我 $1%20$2
最后尝试了一下,也出现了同样的错误。)
有没有更好的解决方案?例如,当我想要捕获 URL 中的空格并将其作为参数传递给底层页面时,我应该如何处理它?
调试 Apache(ErrorLog 带有 LogLevel rewrite:trace6)显示,调用
/FISH%20J12345.6-78919
和
RewriteRule ^(FISH\s*J[0-9\.]+-?\+?[0-9]+)$ myPage.php?sourceName=$1 [L,QSA]
在 mod_rewrite 得到 %20 之前,它正确地将其解码为空格。并且 URL 被重写为
'myPage.php?sourceName=FISH J12345.6-78919'
查询参数中有一个空格,mod_rewrite 不再喜欢这个。
实际上,mod_rewrite 和规则会发生两件事,例如
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
首先解码 URL 的 PATH 部分(请注意 PATH 部分中的 + 是 +,而不是解码为空格)并传递给 mod_rewrite。然后将其放入 $1。原始 URL 的 QUERY 部分未解码,但合并到重写的 PATH 部分。然后将新 URL 交回 Apache。然后 php 解码 QUERY 参数。这导致 PATH 部分被双重解码,因为在重写的 URL 中它是一个 QUERY 参数。
如果没有 [B],例如 /A%2520B/?a=b%2520c
(%25 解码为 %) 将被重写 q=A%20B/&a=b%2520c
为 php 中的 "q" => "A B/", "a" => "b%20c"
。实际上,乍一看并不完全符合预期(至少到目前为止,我所期望的是 "q" => "A%20B/"
)。
因此,无论如何,使用 [B] 将 PATH 部分移动到 QUERY 参数可能是更好的选择,确保它只被解码一次。
使用 [B], /A%2520B/?a=b%2520c
最终被重写为 q=A%2520B%2f&a=b%2520c
在 php 中作为 "q" => "A%20B/", "a" => "b%20c"
。 对我来说看起来更好。
使用 [B],FISH 链接的编码方式如下 escaping backreference 'FISH J12345.6-78919' to 'FISH+J12345%2e6%2d78919'
,因此空格的编码是通过 +(而不是 %20)完成的。在 php 中,它会再次解码。
我认为,对于单编码的 PATH 部分,在大多数情况下不使用 [B] 是可以的,很可能是因为 % 符号在 PATH 部分中用得不多。对我来说,使用 [B] 现在是更好的解决方案。
有一个警告,这里其他地方已经回答过了:由于 + 在 PATH 部分有效,因此 /A+%2bB/
传递给 mod_rewrite 为 A++B/
(因此第一个 + 保持为 + ),最后 q=A%2b%2bB%2f
在 php 中传递为 "q" => "A++B/"
。这无法克服,因为 + 在 PATH 部分和 QUERY 部分的处理方式不同。