如何使用 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
.
有了这个 .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_URI
和 REDIRECT_URL
都会给出“/hello/world”。
有了这个.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
.
有了这个 .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_URI
和 REDIRECT_URL
都会给出“/hello/world”。