.htaccess RewriteRule - DOCUMENT_ROOT和RewriteBase

Jas*_*ary 4 .htaccess mod-rewrite

我有一个安全/子目录,其中有几个文件,我想要执行一些简单的RewriteRules,只是默认PHP扩展.我很难让这些工作,经过一些试验和错误偶然发现了以下情况.

RewriteEngine On
RewriteBase /secure

# Force PHP extension if not a directory
RewriteCond %{DOCUMENT_ROOT}/secure/%{REQUEST_URI} -d
RewriteRule ^(.*)$ - [L]

RewriteCond %{DOCUMENT_ROOT}/secure/$1.php -f
RewriteRule ^((.*/)*[^./]+)/*$ $1.php [L]
Run Code Online (Sandbox Code Playgroud)

我缺乏理解是围绕%{DOCUMENT_ROOT}和追加/secure/.我相信%{DOCUMENT_ROOT}或使用RewriteBase会处理这个.但是,似乎需要这些部件中的每一件.我想知道为什么以及每个人在我的案例中取得的成就.

Tim*_*one 11

在重定向步骤期间,mod_rewrite仅使用RewriteBase指令,并在所有其他处理期间忽略该指令.与文档所说的相反,它通常是没有必要的,因为(如在您的情况下),URL映射到文件系统中的子目录之外是相当常见的DOCUMENT_ROOT.

那么,该指令的作用是什么?当您在使用.htaccess文件时在每个目录上下文中评估规则时,URL会在Apache的请求处理链中很晚地传递给mod_rewrite.这意味着URL可能已经部分转换为文件系统路径,因此/ directory /子目录/文件中的路径实际上可能已经通过/ location /子目录/文件通过Web服务器访问.

这看起来不是什么大问题,但是/ location / piece丢失的事实对mod_rewrite造成了问题.要了解原因,您必须知道mod_rewrite如何使每个目录的上下文重写成为可能.

当您在.htaccess文件中执行重写时,mod_rewrite会将修改后的请求作为内部重定向重新注入Apache,就像它是一个URL一样.这是有问题的,因为请求路径可能不是要传递的适当URL.例如,如果请求最终在/ directory/subdirectory/file(我们假设在其外DOCUMENT_ROOT),我们可能在/directory/.htaccess中有这个规则:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* index.php
Run Code Online (Sandbox Code Playgroud)

这将检查/子目录/文件,确定它不是一个实际的文件,并将其重写为index.php.此时,必须将新URL返回给Apache以进行内部重定向以完成重写.由于它没有引用点,它最终会发送整个路径 - 也就是说,它发送/directory/index.php.这不是您想要的,因为访问此位置的URL实际上是/location/index.php.这就是RewriteBase的用武之地.通过指定

RewriteBase /location/
Run Code Online (Sandbox Code Playgroud)

在.htaccess文件中,目录前缀/目录/将作为此重写后处理的一部分换出/ location /,从而导致内部重定向到预期的URL /location/index.php.

这也对外部重定向有影响.如果您尝试使用[R]仅包含路径的标志进行外部重定向,并且路径没有前导斜杠,则整个目录将以上述方式发送回客户端,除非它被RewriteBase中给出的值替换.

这些点都不会与你的情况相关,所以你应该没有指定RewriteBase.

%{DOCUMENT_ROOT}变量只是Apache内部DOCUMENT_ROOT变量的值,它在服务器/虚拟主机配置中设置.它始终对应于/要求/解析的目录.该-f-d检查需要一个完整的文件系统路径,这就是为什么%{DOCUMENT_ROOT}需要使用它们时,预先准备的相对路径.

但是,为了解析当前请求的路径,mod_rewrite会使用%{REQUEST_FILENAME}变量来处理这个问题.例如,假设.htaccess文件位于/ secure子目录中,您可以按如下方式修改规则集:

RewriteEngine On

# Force PHP extension if not a directory
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]

RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^.*$ $0.php [L]
Run Code Online (Sandbox Code Playgroud)