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

时间:2014-01-11 12:35:31

标签: regex apache .htaccess mod-rewrite url-rewriting

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

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

更新

例如:

webroot

 - sub_directory
 - cms
 - .htaccess

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

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

RewriteBase /sub_directory/

所以我想要像

这样的东西

RewriteBase /%{current_folder}/

4 个答案:

答案 0 :(得分:39)

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

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

然后,您可以在规则中使用%{ENV:BASE}来表示RewriteBase

说明:

此规则的作用是将REQUEST_URIRewriteRule看到的网址路径进行比较,即REQUEST_URI,其中前导RewriteBase被剥离。区别在于RewriteBase,并且已放入%{ENV:BASE}

  • RewriteCond中,LHS(测试字符串)可以使用反向引用变量,例如$1$2%1%2等,但RHS方面即条件字符串无法使用这些$1,{{1} }或$2%1变量。
  • 在RHS条件部分内部,我们可以使用的是内部反向引用,即我们在此条件下捕获的组本身。它们由%2\1等表示。
  • \2首次捕获的群组为RewriteCond。它将由内部反向引用`\ 1。
  • 表示
  • 您可以通过比较(.*?/)RewriteBase来标记此规则基本上是动态查找%{REQUEST_URI}$1的示例将为%{REQUEST_URI},同一示例URI的/directory/foobar.php示例将为$1foobar.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 answerJon 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$

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

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

答案 3 :(得分:0)

如果您在 htaccess 中有 RewriteBase 命令,您可以对其进行注释,然后它将自动解析到该目录。