我遇到一个问题,ApachePHP $_SERVER['REQUEST_URI']
将重写后的 URL 而不是原始请求的 URL 传递给变量。
我进行重写是因为我有一个 WordPress 网站,并且想将其移动到子目录而不是放在根路径中,但仍然希望将其 URL 保留为根 URL。
这种情况并不总是发生。如果我请求,它会用(重写后的 URL)www.xyz.com/wp-admin
填充 PHPREQUEST_URI
变量,但如果我请求(带有尾部斜杠),它实际上会用(重写前的原始 URL)填充 PHP 变量。我想要的是使用重写前的 URL 填充。www.xyz.com/wordpress/wp-admin
www.xyz.com/wp-admin/
REQUEST_URI
www.xyz.com/wp-admin/
REQUEST_URI
我的.htaccess
文件如下:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www.)?xyz.com$
RewriteCond %{REQUEST_URI} !^/wordpress/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /wordpress/$1
RewriteCond %{HTTP_HOST} ^(www.)?xyz.com$
RewriteRule ^(/)?$ wordpress/index.php [L]
</IfModule>`
PHP 版本是 5.3。Apache 版本是 2.4 (Win32)。
更新:我仔细研究了一下,当我输入 URL 时,www.xyz.com/wp-admin
首先会出现 301 重定向www.xyz.com/wordpress/wp-admin/
,但对于(带有尾部斜杠)则不会出现这种情况www.xyz.com/wp-admin/
。对于带有尾部斜杠的 URL,只有重写,正如预期的那样。所以现在的问题是,为什么对于没有尾部斜杠的 URL 首先会发生 301 重定向。
需要澄清的是,没有实际的文件夹/wp-admin/
,但有一个文件夹/wordpress/wp-admin/
。
答案1
该“问题”与 mod_dir 有关(尽管 mod_dir 严格来说不是“该”问题 - 它做了正确的事情并“修复”了 URL)。
由于wp-admin
是物理目录,mod_dir 会通过附加尾部斜杠来“修复” URL(这是正确提供目录索引所必需的,例如index.php
)。它使用 301 重定向来实现这一点。问题是这种情况正在发生后您的内部重写导致重写变成重定向,从而暴露您的/wordpress
子目录。
因此,正确的 URL 严格为/wp-admin/
(末尾带有斜杠)。如果您没有/wordpress
子目录,并且所有内容都在文档根目录中,则 mod_dir 只会重定向/wp-admin
到/wp-admin/
,然后会导致/wp-admin/index.php
提供服务(作为内部子请求)。
您需要做的是手动添加尾部斜杠。如果请求的 URL 不是以斜杠结尾,但会映射到子目录中的物理目录,/wordpress
则添加尾部斜杠(通过外部重定向)。此重定向应该发生前你的内部重写。
因此,请尝试以下操作前您现有的指令:
# Append a slash if it is omitted and would map to a directory
RewriteCond %{REQUEST_URI} !^/wordpress/
RewriteCond %{REQUEST_URI} !/$
RewriteCond %{DOCUMENT_ROOT}/wordpress/$1 -d
RewriteRule (.*) /$1/ [R=302,L]
这样做的目的是,对于任何尚未开始的请求/wordpress/
和不以斜线结尾,但映射到子目录中的物理目录,然后重定向并附加斜线。因此,只要存在目录,/wordpress
请求/wp-admin
就会被重定向。(然后您的内部重写将像以前一样路由 URL。)/wp-admin/
/wordpress/wp-admin
您需要确保清除了浏览器缓存(或者打开浏览器对象检查器进行测试并禁用缓存),因为之前的 301 重定向(由 mod_dir 执行)已经被缓存。
当您确定它工作正常时,请将302
(临时)重定向更改为301
(永久)-如果这是意图。302 被浏览器缓存,因此使测试变得更容易。
在旁边:
ApacheREQUEST_URI
与 PHP$_SERVER['REQUEST_URI']
$_SERVER['REQUEST_URI']
...Apache将重写后的 URL传递给 PHP变量,而不是原始请求的 URL。
Apache 实际上不会REQUEST_URI
直接将 mod_rewrite 中的变量传递给 PHP。尽管这两个变量具有相同的名称,但据我所知,PHP 本身会从请求中填充此变量。
ApacheREQUEST_URI
服务器变量和 PHP 的$_SERVER['REQUEST_URI']
超全局变量实际上包含不同的信息:
- PHP
$_SERVER['REQUEST_URI']
包含查询字符串,而 Apache 的REQUEST_URI
服务器变量不包含;它仅包含 URL 路径。 - PHP
$_SERVER['REQUEST_URI']
包含请求中的原始 URL 路径,而不是重写的 URL。而 Apache 的REQUEST_URI
服务器变量会在整个请求过程中更新以包含重写的 URL。 - URL 路径部分
$_SERVER['REQUEST_URI']
是不是URL 已解码(即 % 已解码)。而 ApacheREQUEST_URI
服务器变量已解码。(注意:URL 的查询字符串部分在 Apache 和 PHP 中始终保持 % 编码。如果您需要检查 Apache 中 % 编码的 URL 路径,请检查THE_REQUEST
Apache 服务器变量。)