.htaccess重写规则-文档根和重写库

.htaccess重写规则-文档根和重写库,.htaccess,mod-rewrite,.htaccess,Mod Rewrite,我有一个secure/sub目录,其中有几个文件,我想对这些文件执行一些简单的重写规则,只是默认了一个PHP扩展名。我花了很长时间才让它们工作起来,经过一些尝试和错误之后,我偶然发现了以下内容 RewriteEngine On RewriteBase /secure # Force PHP extension if not a directory RewriteCond %{DOCUMENT_ROOT}/secure/%{REQUEST_URI} -d RewriteRule ^(.*)$ -

我有一个secure/sub目录,其中有几个文件,我想对这些文件执行一些简单的重写规则,只是默认了一个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]
我对
%{DOCUMENT_ROOT}
和附加
/secure/
缺乏理解。我相信
%{DOCUMENT\u ROOT}
或者使用
重写库
都可以处理这个问题。然而,每一件似乎都是必需的。我想知道为什么以及在我的例子中每个都实现了什么。

mod_rewrite只在重定向步骤中使用,而在所有其他处理过程中忽略。与文档所述相反,这通常是不必要的,因为(在您的案例中)URL映射到文件系统中
文档根目录以外的子目录是相当常见的

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

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

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

这将检查/subdirectory/file,确定它不是实际的文件,并将其重写为index.php。此时,必须向Apache返回一个新的URL,以便内部重定向完成重写。因为它没有参考点,所以它最终会发送整个路径,即发送/directory/index.php。这不是您想要的,因为访问此位置的URL实际上是/location/index.php。这就是RewriteBase的用武之地。通过指定

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

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

不过,这两点似乎都与您的情况不相关,因此您不必指定重写基数就可以了

%{DOCUMENT\u ROOT}
变量只是Apache内部
DOCUMENT\u ROOT
变量的值,该变量在服务器/虚拟主机配置中设置。它始终对应于请求/解析到的目录。
-f
-d
检查需要完整的文件系统路径,这就是为什么在使用它们时,
%{DOCUMENT\u 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]
看看这个
RewriteEngine On

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

RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^.*$ $0.php [L]