将RewriteBasedynamic设置为当前文件夹path
有没有办法将RewriteBase设置为相对于主机根的path当前文件夹(.htaccess文件所在的文件夹)?
我有一个CMS,如果我把它移动到我的主机中的目录,它不工作,除非我把RewriteBase设置为相对于主机根目录的path。 我希望我的CMS只能复制和粘贴,而不需要在htaccess中更改任何代码。
更新:
例如:
webroot - sub_directory - cms - .htaccess
在这种情况下,我应该写在htaccess: RwriteBase /
如果我移动子目录内的htaccess我应该改变RwriteBase为:
RewriteBase /sub_directory/
所以我想要类似的东西
RewriteBase /%{current_folder}/
这里有一种方法可以在环境variables中获取RewriteBase
,然后在其他重写规则中使用它们:
RewriteCond %{REQUEST_URI}::$1 ^(.*?/)(.*)::\2$ RewriteRule ^(.*)$ - [E=BASE:%1]
然后,您可以在规则中使用%{ENV:BASE}
来表示RewriteBase
。
说明:
此规则通过将REQUEST_URI
与RewriteRule
看到的URLpath进行比较,即将REQUEST_URI
与剥离开的RewriteBase
。 不同之处在于RewriteBase
,并放入%{ENV:BASE}
。
- 在
RewriteCond
,LHS(testingstring)可以使用反向引用variables,例如$1
,$2
OR%1
,%2
等,但RHS方即条件string不能使用这些$1
,$2
OR%1
,%2
variables。 - 在RHS条件部分里面,只有反向参考我们可以使用的是内部反向参考,即我们在这种条件下捕获的组。 它们由
\1
,\2
等表示 - 在
RewriteCond
第一个捕获的组是(.*?/)
。 它将由内部的反向引用'\ 1'表示。 - 正如你可以注意到这个规则基本上是通过比较
%{REQUEST_URI}
和$1
RewriteBase
dynamic地findRewriteBase
。%{REQUEST_URI}
的一个例子是foobar.php
,同样例子的URI例子是foobar.php
。^(.*?/)(.*)::\2$
将第一个捕获组%1
或\1
的差异。 对于我们的例子来说,它将%1
或\1
填充到设置envvariables%{BASE}
即E=BASE:%1
后使用的值/directory/
中。
在anubhava的回答和Jon Lin的基础上 ,我刚刚为自己提出了这个问题(还没有在生产中使用过,也没有广泛的testing过)。
让我们使用这个示例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:CWD}index.html [END]
您可以通过在Apache的httpd.conf
中使用LogLevel alert rewrite:trace6
来查看自己正在发生的事情的细节,然后查看error.log
。
下面的两行更加清晰,我仍然觉得有些困惑。
RewriteCond %{ENV:SUBPATH}::%{REQUEST_URI} ^(.*)::(.*?)\1$ RewriteRule ^ - [ENV=CWD:%2]
首先,双冒号::
不是任何types的操作符; 这只是一个任意的分隔符。 RewriteCond
将TestString %{ENV:SUBPATH}::%{REQUEST_URI}
展开为以下内容:
misc/subdir/file.xyz::/path_to/current_folder/misc/subdir/file.xyz
那么我们的CondPattern ^(.*)::(.*?)\1$
:
-
^(.*)::
matchesmisc/subdir/file.xyz::
-
\1
是第一个捕获组,misc/subdir/file.xyz
-
(.*?)\1$
成为(.*?)misc/subdir/file.xyz$
- 因此,我们的第二个捕获组
(.*?)
匹配剩余的/path_to/current_folder/
而我们的RewriteRule
将CWD
设置为%2
,这是CondPattern的第二个捕获组。
我认为,接受的解决scheme对我来说不起作用,但是这样做: 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]