为什么 Apache RewriteRule 对 '&' 和 '?' 的处理方式相同

问题描述

我正在尝试为 Apache 网络服务器中的“.htaccess”文件编写自定义重写规则。

主要思想是处理表单中的请求:

example.com/foo

到 www_root 中的“index.PHP文件

example.com/index.PHP?queryString1=foo

众所周知,这很容易做到。只需在“.htaccess”文件添加以下几行:

RewriteEngine on
RewriteCond %{REQUEST_URI} !-f
RewriteCond %{REQUEST_URI} !-d
RewriteCond %{REQUEST_URI} !-l
RewriteRule ^(.*)$ index.PHP?queryString1=$1 [QSA,L]

但问题是当我们想在请求中添加一个查询字符串时,例如如下:

example.com/foo?queryString2=bar&queryString3=baz

与我的预期相反,以下 URL 的作用相同:

example.com/foo&queryString2=bar&queryString3=baz

我不希望执行第二种情况(其中第二个查询字符串以 '&' 开头)。 另外,如果您在“index.PHP文件中写入:

<?PHP echo '<pre>'.print_r($_SERVER['QUERY_STRING'],TRUE).'</pre>'; ?>

然后,两个 URL(example.com/foo?queryString2=bar&queryString3=bazexample.com/foo&queryString2=bar&queryString3=baz)的输出将是唯一的:

queryString1=foo&queryString2=bar&queryString3=baz

谁能解释我在“.htaccess”文件中的代码有什么问题?谢谢。

解决方法

经过上面的讨论,apache2 不处理 & 和 ?以同样的方式。 “?”是来自 QUERY_STRING 的 URL 的分隔符,但 & 是作为 apache2 RewriteRule 匹配的 URL 的一部分的普通字符。

https://www.example.com/URL?QUERY_STRING 模式中,URL 只被 .htaccess 文件中的 RewriteRule 匹配,如果给定,则是主机名和端口之后的字符串,查询字符串 ref. 之前的字符串,没有前导斜杠 / .

小心,在 apache2 配置文件 vhosts.conf 或类似文件中,在 apache2 服务器启动时读取 RewriteRule mathches 对 var users = document.getElementById("oneUser").innerText; 字符串(是的,带前导斜杠)。

OP 的情况只是一个机会,而不是一般规则。如果 & 包含在 URL 中,我已经通过触发 /URL 错误来对此解决方案进行测试:

404 Not Found

RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-l RewriteRule ^([^&]*)$ index.php?queryString1=$1 [QSA,L] 将产生 404 错误。

example.com/foo&queryString2=bar&queryString3=baz%{REQUEST_FILENAME} 好。

字符范围 [^&] 表示除 & 以外的任何字符。使用正则表达式 ^([^&]*)$,我们选择一个不包含 & 的字符串,从开始由 ^ 表示,到由 $ 表示的结束,所以 & 符号自由。