将 RewriteBase 动态设置为当前文件夹路径

Posted

技术标签:

【中文标题】将 RewriteBase 动态设置为当前文件夹路径【英文标题】:Set RewriteBase to the current folder path dynamically 【发布时间】:2014-01-30 11:41:27 【问题描述】:

有没有办法将 RewriteBase 设置为相对于主机根目录的路径当前文件夹(.htaccess 文件所在的文件夹)?

我有一个 CMS,如果我将它移动到主机中的目录,它就不起作用,除非我将 RewriteBase 设置为相对于主机根目录的目录路径。我希望我的 CMS 只使用复制和粘贴,而不更改 htaccess 中的任何代码。

更新:

例如:

webroot

 - sub_directory
 - cms
 - .htaccess

在这种情况下,我应该在 htaccess 中写:RewriteBase /

如果我将 htaccess 移动到 sub_directory 中,我应该将 RewriteBase 更改为:

RewriteBase /sub_directory/

所以我想要类似的东西

RewriteBase /%current_folder/

【问题讨论】:

那是相对于文档根目录的? 查看更新@Sumurai8 【参考方案1】:

这是一种可以在环境变量中获取RewriteBase 的方法,然后您可以在其他重写规则中使用它:

RewriteCond %REQUEST_URI::$1 ^(.*?/)(.*)::\2$
RewriteRule ^(.*)$ - [E=BASE:%1]

那么你可以在你的规则中使用%ENV:BASE来表示RewriteBase,即:

#redirect in-existent files/calls to index.php
RewriteCond %REQUEST_FILENAME !-f 
RewriteRule . %ENV:BASE/index.php [L]

说明:

此规则通过将REQUEST_URIRewriteRule 看到的URL 路径进行比较,即REQUEST_URI 去掉了前导RewriteBase。区别在于RewriteBase 被放入%ENV:BASE

RewriteCond 中,LHS(测试字符串)可以使用反向引用变量,例如$1$2%1%2 等,但 RHS 端即条件字符串 不能使用 这些 $1$2%1%2 变量。 在 RHS 条件部分中,我们可以使用的唯一反向引用是内部反向引用,即我们在此条件本身中捕获的组。它们用\1\2等表示。 在RewriteCond 第一个捕获的组中是(.*?/)。它将由内部反向引用 \1 表示。 您可以看出,这条规则基本上是通过比较%REQUEST_URI$1 动态找到RewriteBase%REQUEST_URI 的示例将是 /directory/foobar.php$1 的示例对于同一示例 URI 将是 foobar.php^(.*?/)(.*)::\2$ 将差异放在第一个捕获组 %1\1 中。对于我们的示例,它将使用值/directory/ 填充%1\1,该值稍后用于在E=BASE:%1 中设置环境变量%ENV:BASE

【讨论】:

能否更改这两个命令以匹配包含多个正斜杠的 URL?例如,这将不起作用:/directory/a///b/c/(注意 a 后面的 3 个斜杠) 是的,使用重定向规则所有多个斜杠应首先修剪为单个/ 今天,五年多之后,你可能挽救了我的理智。谢谢!这开始吞噬我的灵魂!【参考方案2】:

我认为接受的解决方案对我不起作用,但确实如此:https://web.archive.org/web/20180401034514/http://www.zeilenwechsel.de/it/articles/8/Using-mod_rewrite-in-.htaccess-files-without-knowing-the-RewriteBase.html

长话短说:

RewriteBase /
RewriteCond %REQUEST_FILENAME !-f
RewriteCond $0#%REQUEST_URI ([^#]*)#(.*)\1$
RewriteRule ^.*$ %2index.php [QSA,L]

【讨论】:

伙计,你救了我的命,这件作品 100% 有效,而且它不像鞋面那样短。如果我能竖起大拇指。 我已将链接更改为使用 archive.org 。未来打样:castledragmire.com/misc/HTAccessPost.png【参考方案3】:

在anubhava's answer 和Jon Lin's 的基础上,这是我自己想出的(尚未在生产中使用过,也没有进行过广泛的测试)。

让我们使用这个示例 URL,其中 .htaccess 在 current_folder 中:

http://localhost/path_to/current_folder/misc/subdir/file.xyz

文件系统:/var/www/webroot/path_to/current_folder/.htaccess

Options +FollowSymLinks
RewriteEngine On
RewriteBase /

RewriteCond %ENV:SUBPATH ^$  # Check if variable is empty. If it is, process the next rule to set it.
RewriteRule ^(.*)$ - [ENV=SUBPATH:$1]
# SUBPATH is set to 'misc/subdir/file.xyz'

RewriteCond %ENV:CWD ^$
RewriteCond %ENV:SUBPATH::%REQUEST_URI ^(.*)::(.*?)\1$
RewriteRule ^ - [ENV=CWD:%2]
# CWD is set to '/path_to/current_folder/'

RewriteCond %ENV:FILENAME ^$
RewriteCond %REQUEST_URI ^.*/(.*)$
RewriteRule ^ - [ENV=FILENAME:%1]
# FILENAME is set to 'file.xyz'

# Check if /var/www/webroot/path_to/current_folder/misc/subdir/file.xyz exists.
# -f checks if a file exists, -d checks for a directory.
# If it exists, rewrite to /path_to/current_folder/misc/subdir/file.xyz and stop processing rules.
RewriteCond %ENV:SUBPATH ^.+$  # Ensure SUBPATH is not empty
RewriteCond %DOCUMENT_ROOT%ENV:CWD%ENV:SUBPATH -f [OR]
RewriteCond %DOCUMENT_ROOT%ENV:CWD%ENV:SUBPATH -d
RewriteRule ^.*$ %ENV:CWD%ENV:SUBPATH [END]

# Check if /var/www/webroot/path_to/current_folder/file.xyz exists.
# If it exists, rewrite to /path_to/current_folder/file.xyz and stop processing rules.
RewriteCond %ENV:FILENAME ^.+$
RewriteCond %DOCUMENT_ROOT%ENV:CWD%ENV:FILENAME -f [OR]
RewriteCond %DOCUMENT_ROOT%ENV:CWD%ENV:FILENAME -d
RewriteRule ^.*$ %ENV:CWD%ENV:FILENAME [END]

# Else, rewrite to /path_to/current_folder/index.html and stop processing rules.
RewriteRule ^.*$ %ENV:CWDindex.html [END]

您可以通过在 apache 中的 httpd.conf 中使用 LogLevel alert rewrite:trace6,然后查看您的 error.log,来查看自己发生的事情的详细信息。

这里对以下两行进行了更多说明,我仍然觉得有些混乱。

RewriteCond %ENV:SUBPATH::%REQUEST_URI ^(.*)::(.*?)\1$
RewriteRule ^ - [ENV=CWD:%2]

首先,双冒号:: 不是任何类型的运算符;它只是一个任意分隔符。 RewriteCond 将 TestString %ENV:SUBPATH::%REQUEST_URI 扩展为以下内容:

misc/subdir/file.xyz::/path_to/current_folder/misc/subdir/file.xyz

然后是我们的 CondPattern ^(.*)::(.*?)\1$:

    ^(.*):: 匹配 misc/subdir/file.xyz:: \1 是第一个捕获组,misc/subdir/file.xyz (.*?)\1$ 变为 (.*?)misc/subdir/file.xyz$ 因此,我们的第二个捕获组(.*?) 匹配剩余的/path_to/current_folder/

而我们的RewriteRuleCWD 设置为%2,这是CondPattern 的第二个捕获组。

【讨论】:

【参考方案4】:

如果你在 htaccess 中有RewriteBase 命令,你可以评论它,然后它会自动解析到那个目录。

【讨论】:

以上是关于将 RewriteBase 动态设置为当前文件夹路径的主要内容,如果未能解决你的问题,请参考以下文章

一个 .htaccess 文件中有多个 RewriteBase?

apache_conf 为.htaccess文件创建可靠的基础。目前包括RewriteBase,Security(针对索引,文件等)和Expires Headers

.htaccess 移除 RewriteBase

如何将默认时间设置为当前时间 mongo 模式?

在这种情况下删除“RewriteBase /”是不是安全[重复]

如何在变量打字稿中动态设置当前时间