将 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_URI
与RewriteRule
看到的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/
而我们的RewriteRule
将CWD
设置为%2
,这是CondPattern 的第二个捕获组。
【讨论】:
【参考方案4】:如果你在 htaccess 中有RewriteBase
命令,你可以评论它,然后它会自动解析到那个目录。
【讨论】:
以上是关于将 RewriteBase 动态设置为当前文件夹路径的主要内容,如果未能解决你的问题,请参考以下文章
一个 .htaccess 文件中有多个 RewriteBase?
apache_conf 为.htaccess文件创建可靠的基础。目前包括RewriteBase,Security(针对索引,文件等)和Expires Headers