有没有办法将RewriteBase设置为相对于主机根目录的当前文件夹(.htaccess文件所在的文件夹)?
我有一个CMS,如果我将它移动到我的主机中的目录,它将无法工作,除非我将RewriteBase设置为相对于主机根目录的路径。我希望我的CMS只能使用复制和粘贴,而无需更改htaccess中的任何代码。
例如:
webroot
- sub_directory
- cms
- .htaccess
在这种情况下,我应该写入htaccess:RewriteBase /
如果我在sub_directory中移动htaccess,我应该将RewriteBase更改为:
RewriteBase /sub_directory/
所以我想要像
这样的东西 RewriteBase /%{current_folder}/
答案 0 :(得分:39)
以下是一种可以在环境变量中获取RewriteBase
的方法,然后可以在其他重写规则中使用它:
RewriteCond %{REQUEST_URI}::$1 ^(.*?/)(.*)::\2$
RewriteRule ^(.*)$ - [E=BASE:%1]
然后,您可以在规则中使用%{ENV:BASE}
来表示RewriteBase
。
此规则的作用是将REQUEST_URI
与RewriteRule
看到的网址路径进行比较,即REQUEST_URI
,其中前导RewriteBase
被剥离。区别在于RewriteBase
,并且已放入%{ENV:BASE}
。
RewriteCond
中,LHS(测试字符串)可以使用反向引用变量,例如$1
,$2
或%1
,%2
等,但RHS方面即条件字符串无法使用这些$1
,{{1} }或$2
,%1
变量。%2
,\1
等表示。\2
首次捕获的群组为RewriteCond
。它将由内部反向引用`\ 1。(.*?/)
和RewriteBase
来标记此规则基本上是动态查找%{REQUEST_URI}
。 $1
的示例将为%{REQUEST_URI}
,同一示例URI的/directory/foobar.php
示例将为$1
。 foobar.php
正在区分第一个被捕获的小组^(.*?/)(.*)::\2$
或%1
。对于我们的示例,它将使用值\1
填充%1
或\1
,稍后在设置env变量/directory/
时使用该值%{BASE}
。答案 1 :(得分:7)
我认为,接受的解决方案对我不起作用,但这样做: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]
答案 2 :(得分:4)
在anubhava's answer和Jon Lin's的基础上,这就是我刚给自己想出来的内容(还没有在生产中使用它,也没有广泛地测试过它)。
让我们使用这个示例网址,其中.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:CWD}index.html [END]
您可以在apache中的LogLevel alert rewrite:trace6
中使用httpd.conf
查看自己所发生事件的详细信息,然后查看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的第二个捕获组。
答案 3 :(得分:0)
如果您在 htaccess 中有 RewriteBase
命令,您可以对其进行注释,然后它将自动解析到该目录。