2

有了这个.htaccess

RewriteEngine On
RewriteRule foo/(.*) /foo-$1         # 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 也修改REQUEST_URIPHP 将看到的内容?

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

当替换字符串不是文件路径而是应该由下一个规则处理的 URL 时,另请参见RewriteRule 。

4

3 回答 3

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-$1
RewriteRule . index.php [L]

确保添加这一行:

php_value auto_prepend_file "before.php" 

之前的.php

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

像:

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

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

索引.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-$1 [L] # please note [L] here
RewriteRule . index.php [L]

因此 before.php 可以替换为:

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

更新解决方案2;使用 mod_proxy

发现您还可以使用 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-$1 [L,P]
RewriteRule . index.php 

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

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

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

于 2021-11-11T14:09:05.443 回答
1

PHP$_SERVER['REQUEST_URI']返回 Apacheoriginal-uri而不是current-uri.

CGIVar 指令

使用此.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和提供“/hello/world” REDIRECT_URL

于 2021-11-15T16:33:28.693 回答
0

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

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

于 2021-11-10T13:21:59.833 回答