如何使用 RewriteRule 使得 $_SERVER['REQUEST_URI'] 也被修改为 PHP?

How to use RewriteRule such that $_SERVER['REQUEST_URI'] is modified too for PHP?

有了这个.htaccess:

RewriteEngine On
RewriteRule foo/(.*) /foo-         # here I tried [L], [PT], [C], etc.
RewriteRule . index.php [L]

我已经为第一个 RewriteRule 尝试了所有可能的标志,但总是,这个 PHP 代码:

<?php echo $_SERVER['REQUEST_URI']; ?>

在访问 http://example.com/foo/bar 时总是回显 /foo/bar 而不是 /foo-bar。为什么?

如何让 Apache 的 RewriteEngine 也修改将被 PHP 看到的 REQUEST_URI

注意:我不想要 [R],因为重定向会生成新的浏览器请求,并更改 URL 栏中显示的 URL,这是我不想要的。

另见

经过进一步研究,PHP似乎总是会在$_SERVER['REQUEST_URI']中看到原始的URL,而不是RewriteRule的目标。 (此处需要权威来源)。

顺便说一句,RewriteRule 的目标通常是 将处理请求的文件 ,除非我们使用 [R] 重定向标志,那么在这种情况下浏览器将对新的 URL 进行新的请求(并且浏览器 URL 栏发生变化)。

我认为如果不采取一些变通办法,您尝试做的事情是不可能的。 我在这个 post 中提供了 2 个解决方案,一个使用 auto_prepend_file,一个使用 mod_proxy.

解决方案 1:使用 auto_prepend_file

请看下面的脚本,这里并没有直接设置REQUEST_URI全局,而是覆盖了PHP,代码如下:

.htaccess

php_value auto_prepend_file "before.php" 

RewriteEngine On
RewriteRule foo/(.*) /foo-
RewriteRule . index.php [L]

确保添加这一行:

php_value auto_prepend_file "before.php" 

before.php

在此脚本中,您可以替换 REQUEST_URI:

喜欢:

$_SERVER['REQUEST_URI'] = "/" . str_replace('/', '-', ltrim($_SERVER['REQUEST_URI'], "/"));

你可以进一步改进这个脚本,但我认为概念很清楚。

index.php

Index.php 不受影响但包含重写的规则:

var_dump($_SERVER['REQUEST_URI']); //string(7) "/foo-bar"

http://localhost/foo/bar?test 的请求现在是:string(13) "/foo-bar?test"

更新

使用[L]时,可以通过以下方式获得重写的url:

var_dump($_SERVER['REDIRECT_URL']); # /foo-bar

因此 .htaccess 变为:

php_value auto_prepend_file "before.php" 

RewriteEngine On
RewriteRule foo/(.*) /foo- [L] # please note [L] here
RewriteRule . index.php [L]

因此 before.php 可以替换为:

$_SERVER['REQUEST_URI'] = $_SERVER['REDIRECT_URL'];

更新解决方案2;使用 mod_proxy

发现您还可以使用 mod 代理:

我必须启用以下 mod 规则:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so

现在您的 .htaccess 已更改为(注意 [P] 标志):

RewriteEngine On
RewriteRule ^foo/(.+)$ /foo- [L,P]
RewriteRule . index.php 

这会将所有 foo/bar 请求代理到 /foo-bar 并相应地更改 $_SERVER['REQUEST_URI']

var_dump($_SERVER['REQUEST_URI']); //output: string(8) "/foo-bar"

我认为使用 PHP 前置文件是一种更有效的方法。

PHP 的 $_SERVER['REQUEST_URI'] returns Apache original-uri 而不是 current-uri.

CGIVar Directive

有了这个 .htaccess 文件:

CGIVar REQUEST_URI current-uri
RewriteRule (.*) index.php [L]

然后对 example.com/hello/world 的请求将给出:

$_SERVER["REQUEST_URI"]  "/index.php"
$_SERVER["REDIRECT_URL"] "/hello/world" 

如果没有 CGIVar 行,REQUEST_URIREDIRECT_URL 都会给出“/hello/world”。