Apache 的 mod_rewrite 和 PHP 的 REQUEST_URI 变量

Mg5*_*512 6 php mod-rewrite rewrite apache-2.4 apache2

我有一个问题,ApachePHP $_SERVER['REQUEST_URI']在 URL 被重写而不是原始请求后将 URL传递给变量。

我正在做这个重写,因为我有一个 WordPress 网站,想把它移动到一个子目录而不是把它放在根路径中,但仍然想保持它的 URL 作为根 URL。

这不会一直发生。如果我请求www.xyz.com/wp-admin它填充 PHPREQUEST_URI变量www.xyz.com/wordpress/wp-admin(这是重写后的 URL),但如果我请求www.xyz.com/wp-admin/(带有尾部斜杠),它实际上填充 PHPREQUEST_URI变量www.xyz.com/wp-admin/(重写之前的原始 URL)。我想要的是REQUEST_URI在重写之前用 URL 填充。

我的.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>`
Run Code Online (Sandbox Code Playgroud)

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/(带有斜杠)。对于带有尾部斜杠的那个,正如预期的那样,只有重写。所以现在的问题是为什么 301 重定向首先发生在没有尾部斜杠的 URL 上。

澄清一下,没有实际的文件夹/wp-admin/,但有一个文件夹/wordpress/wp-admin/

MrW*_*ite 3

“问题”与 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]
Run Code Online (Sandbox Code Playgroud)

其作用是,对于尚未开始/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_REQUESTApache 服务器变量。)